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:
Mon Jan 26 18:56:52 2015 +0000
Revision:
26:942faa4201d5
Parent:
25:1c6c2895f729
Works for both "Nordic nRF51822" and "Nordic nRF51822 FOTA" platforms, and the FOTA load does allow subsequent FOTA loads using Android App "nRF Master Control Panel".

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 9:2d11beda333f 4 // - http://developer.mbed.org/users/jksoft/code/BLE_RCBController/ (Setting up a custom Service/Characteristic)
prussell 0:0217a862b047 5 // - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 0:0217a862b047 6 // - https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LoopbackUART/
prussell 1:4a25d917fb6a 7 // - https://developer.mbed.org/users/takafuminaka/code/BLE_HTM_by_InTempSensr/
prussell 6:5b6fb35b4450 8 // - https://developer.mbed.org/users/garimagupta002/notebook/ble-uart-lcd-demo/ (Advertise UUID16+UUID128)
prussell 10:ee3a359f7d3f 9 // - http://developer.mbed.org/teams/UCL-IoT/code/BLE_LED_Controller/ (With matching Android App, uses BLE-UART)
prussell 10:ee3a359f7d3f 10 // - https://developer.mbed.org/users/todotani/code/BLE_Health_Thermometer2-010/wiki/BLE_Health_Thermometer2-010 //Temperature handles
prussell 23:78aad4e53ae2 11 // - https://developer.mbed.org/users/rosterloh84/code/Buddi_Blueband (Disconnect Reasons)
prussell 0:0217a862b047 12 // - miscellaneous adopted from more samples...
prussell 0:0217a862b047 13 // Reference:
prussell 22:533275e76f55 14 // - nRF51822:
prussell 22:533275e76f55 15 // - MKit Pins: http://developer.mbed.org/users/mbed_official/code/mbed-src/file/c80ac197fa6a/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/TARGET_NRF51822_MKIT/PinNames.h
prussell 22:533275e76f55 16 // - Platform: http://developer.mbed.org/platforms/Nordic-nRF51822/
prussell 22:533275e76f55 17 // - MCU: http://developer.mbed.org/users/mbed_official/code/mbed-src/file/d2c15dda23c1/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822
prussell 0:0217a862b047 18 // - http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/
prussell 0:0217a862b047 19 // - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/docs/tip/
prussell 0:0217a862b047 20 // - Reference: http://developer.mbed.org/teams/Bluetooth-Low-Energy/
prussell 0:0217a862b047 21 // Warnings:
prussell 0:0217a862b047 22 // - As of 20141210 it is necessary to use Android App [nRF-Master Control Panel] to ensure any previous connected
prussell 0:0217a862b047 23 // code on mkit is properly Disconnected before trying to connect other Android nRF Apps (nRFToolbox, nRF UART 2.0, etc.).
prussell 22:533275e76f55 24 // As UART device doesn't offer disconnect you may need to load a non-uart sample, then use MCP to connect and discoonect, to clear the link.
prussell 0:0217a862b047 25 // Notes:
prussell 10:ee3a359f7d3f 26 // - onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range, and no onDataSent() with App nRF-MCP.
prussell 0:0217a862b047 27 // - onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range, OnTimeout didn't occur at all.
prussell 0:0217a862b047 28 // ToDo: and ToCheck:
prussell 8:f187ba55aed2 29 // - 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 30 // - Re-check where voltatile needed
prussell 23:78aad4e53ae2 31 // - ToCheck(Maybe in App): device.CreateBond(), device.SetPairingConfirmation(), gatt.refresh(to clear ble cache when changing services in devlopment)
prussell 8:f187ba55aed2 32 // - 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 11:7d02fe5ebea5 33 // - invalid or untested reference code commented with "//x ", feel free to delete or experiment
prussell 11:7d02fe5ebea5 34 // - valid alternate code commented with "//a " prefix to indicate alternnative is valid code
prussell 0:0217a862b047 35 //==========End of PR's Header
prussell 0:0217a862b047 36
prussell 0:0217a862b047 37 //==========Historic Licencing from original imported sample from mbed website [BLE_HeartRate] ==========
prussell 0:0217a862b047 38 //From: http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 0:0217a862b047 39 /* mbed Microcontroller Library
prussell 0:0217a862b047 40 * Copyright (c) 2006-2013 ARM Limited
prussell 0:0217a862b047 41 *
prussell 0:0217a862b047 42 * Licensed under the Apache License, Version 2.0 (the "License");
prussell 0:0217a862b047 43 * you may not use this file except in compliance with the License.
prussell 0:0217a862b047 44 * You may obtain a copy of the License at
prussell 0:0217a862b047 45 * http://www.apache.org/licenses/LICENSE-2.0
prussell 0:0217a862b047 46 * Unless required by applicable law or agreed to in writing, software
prussell 0:0217a862b047 47 * distributed under the License is distributed on an "AS IS" BASIS,
prussell 0:0217a862b047 48 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
prussell 0:0217a862b047 49 * See the License for the specific language governing permissions and
prussell 0:0217a862b047 50 * limitations under the License. */
prussell 0:0217a862b047 51 //==========end of Historic Licencing ==========
prussell 0:0217a862b047 52
prussell 0:0217a862b047 53
prussell 0:0217a862b047 54 //==========Compile Options==========
prussell 11:7d02fe5ebea5 55 #define ENABLE_uSerial 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 11:7d02fe5ebea5 56 //x #define ENABLE_BLE_SLOW 0 //PR: Option to slow the connection interval possibly saving power (After Connected) -- Imported feature never tested
prussell 0:0217a862b047 57
prussell 0:0217a862b047 58 //==========Includes==========
prussell 9:2d11beda333f 59 #include "mbed.h" // mbed
prussell 1:4a25d917fb6a 60 #include "BLEDevice.h" // BLE
prussell 1:4a25d917fb6a 61 #include "nrf_soc.h" // nRF Internal Temperature Sensor
prussell 0:0217a862b047 62
prussell 0:0217a862b047 63 //Services
prussell 0:0217a862b047 64 #include "BatteryService.h"
prussell 0:0217a862b047 65 #include "DeviceInformationService.h"
prussell 5:d36bbb315e31 66 #include "HealthThermometerService.h"
prussell 0:0217a862b047 67 #include "HeartRateService.h"
prussell 5:d36bbb315e31 68 #include "LinkLossService.h" //TODO: How support this?
prussell 8:f187ba55aed2 69 //#include "DFUService" //TODO: DFU and FOTA Support
prussell 0:0217a862b047 70 //#include "UARTService.h" //TODO: Add a UART Channel for streaming data like logs?
prussell 0:0217a862b047 71
prussell 0:0217a862b047 72 //==========Debug Console==========
prussell 11:7d02fe5ebea5 73 #if ENABLE_uSerial
prussell 11:7d02fe5ebea5 74 //Restart TeraTerm just before Pressing Reset on mbed, Default Serual=9600-8N1(No Flow Control)
prussell 10:ee3a359f7d3f 75 //Using default baud rate to avoid issues with DEBUG in a constructor being at default baud rate before main()
prussell 11:7d02fe5ebea5 76 //TeraTerm: http://en.sourceforge.jp/projects/ttssh2/releases/
prussell 11:7d02fe5ebea5 77 Serial debug_userial(USBTX, USBRX); //PR: DebugSerialOverMbedUSB
prussell 11:7d02fe5ebea5 78 #define DEBUG(...) { debug_userial.printf(__VA_ARGS__); }
prussell 0:0217a862b047 79 #else
prussell 6:5b6fb35b4450 80 #define DEBUG(...) //Do Nothing, DEBUG() lines are ignored
prussell 0:0217a862b047 81 #endif
prussell 0:0217a862b047 82
prussell 2:c77c2b06d604 83 //========== This Section is to Create Debug output showing variable prep before main() ==========
prussell 2:c77c2b06d604 84 bool u8_prep_dummy(void) {
prussell 6:5b6fb35b4450 85 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 86 return true;
prussell 2:c77c2b06d604 87 }
prussell 2:c77c2b06d604 88 const bool bPrep = u8_prep_dummy();
prussell 2:c77c2b06d604 89
prussell 11:7d02fe5ebea5 90 //========== IO Hardware: Buttons, LEDs, PWM ==========
prussell 12:8bac5f5d3a3e 91 // Inputs: (Simultaneous DigitalIn and InteruptIn is OK)
prussell 22:533275e76f55 92 DigitalIn bB1in(BUTTON1); //nRF51822p0.16==pin22 //if(bB1in){}
prussell 22:533275e76f55 93 DigitalIn bB2in(BUTTON2); //nRF51822p0.17==pin25 //if(bB2in){}
prussell 23:78aad4e53ae2 94 InterruptIn B1int(BUTTON1); //nRF51822p0.16==pin22 //B1int.rise(&onB1rise);
prussell 23:78aad4e53ae2 95 InterruptIn B2int(BUTTON2); //nRF51822p0.17==pin25 //B1int.fall(&onB1fall);
prussell 11:7d02fe5ebea5 96
prussell 11:7d02fe5ebea5 97 // Outputs:
prussell 12:8bac5f5d3a3e 98 //a DigitalOut bL1out(LED1); // Direct LED1 drive
prussell 12:8bac5f5d3a3e 99 //a DigitalOut bL2out(LED2); // Direct LED2 drive
prussell 12:8bac5f5d3a3e 100 PwmOut fL1pwm(LED1); float fL1level = 0.1; // PWM LED1, brightness=float(0.0~1.0)
prussell 12:8bac5f5d3a3e 101 PwmOut fL2pwm(LED2); float fL2level = 0.1; // PWM LED2, brightness=float(0.0~1.0)
prussell 12:8bac5f5d3a3e 102 bool bAppControl = false; //Flag: Host has control of LEDs through BLE
prussell 11:7d02fe5ebea5 103
prussell 12:8bac5f5d3a3e 104 //a volatile uint8_t uB1rise; void onB1rise(void){ uB1rise++; };// Flag Event, Counter helps detect missed events since last cleared
prussell 12:8bac5f5d3a3e 105 //a volatile uint8_t uB1fall; void onB1fall(void){ uB1fall++; };// Flag Event, Counter helps detect missed events since last cleared
prussell 12:8bac5f5d3a3e 106 //a volatile uint8_t uB2rise; void onB2rise(void){ uB2rise++; };// Flag Event, Counter helps detect missed events since last cleared
prussell 12:8bac5f5d3a3e 107 //a volatile uint8_t uB2fall; void onB2fall(void){ uB2fall++; };// Flag Event, Counter helps detect missed events since last cleared
prussell 0:0217a862b047 108
prussell 22:533275e76f55 109 //========== ADC ==========
prussell 22:533275e76f55 110 // ADC/Analog: 20150106PR
prussell 22:533275e76f55 111 // - Options:
prussell 22:533275e76f55 112 // - AnalogIn, Default: http://developer.mbed.org/handbook/AnalogIn
prussell 22:533275e76f55 113 // - ADC Lib, http://developer.mbed.org/users/simonb/code/ADC_test/
prussell 22:533275e76f55 114 // - Fast, but burns power: http://developer.mbed.org/users/Sissors/code/FastAnalogIn/
prussell 22:533275e76f55 115 // Initially using the mbed standard: AnalogIn (Later may change when power or timing require it)
prussell 22:533275e76f55 116 // - adcX.read() returns a float, scaled so 0.0~1.0 == ADC range 0~Vcc (0.3 == 30% of Vcc)
prussell 22:533275e76f55 117 // - adcX.read_u16() returns uint16, raw (0x0000~0xFFFF)
prussell 22:533275e76f55 118 //nRF51822 mkit Analog Pins are only p1~p6 (P0_1~P0_6):
prussell 22:533275e76f55 119 //AnalogIn adc0(p26);// nRF51822p0.26==pin45==AIN0==XL2 (Reserve for low power 32KHz Crystal)
prussell 22:533275e76f55 120 //AnalogIn adc1(p27);// nRF51822p0.27==pin46==AIN1==XL1 (Reserve for low power 32KHz Crystal)
prussell 22:533275e76f55 121 //AnalogXX AREF0 // nRF51822p0.00==pin04 ==AREF0 (Reserve for Analog Reference)
prussell 22:533275e76f55 122 AnalogIn adcA(p1); // nRF51822p0.01==pin05==AIN2
prussell 22:533275e76f55 123 AnalogIn adcB(p2); // nRF51822p0.02==pin06==AIN3
prussell 22:533275e76f55 124 //AnalogIn adcC(p3); // nRF51822p0.03==pin07==AIN4
prussell 22:533275e76f55 125 //AnalogIn adcD(p4); // nRF51822p0.04==pin08==AIN5
prussell 22:533275e76f55 126 //AnalogIn adcE(p5); // nRF51822p0.05==pin09==AIN6
prussell 22:533275e76f55 127 //AnalogIn adcF(p6); // nRF51822p0.06==pin10==AIN7==AREF1 (Option: Reserve for Analog Reference)
prussell 22:533275e76f55 128
prussell 22:533275e76f55 129 void vShowADC(void)
prussell 22:533275e76f55 130 { //TODO: Check what the actual ADC register settings are to know how the nRF51822 is actually configured
prussell 25:1c6c2895f729 131 DEBUG(" ShowADC:");
prussell 25:1c6c2895f729 132 DEBUG(" p1=AIN2 0x%04X %f,", adcA.read_u16(), adcA.read() );
prussell 25:1c6c2895f729 133 DEBUG(" p2=AIN3 0x%04X %f,", adcB.read_u16(), adcB.read() );
prussell 25:1c6c2895f729 134 //DEBUG(" p3=AIN4 0x%04X %f,", adcC.read_u16(), adcC.read() );
prussell 25:1c6c2895f729 135 //DEBUG(" p4=AIN5 0x%04X %f,", adcD.read_u16(), adcD.read() );
prussell 25:1c6c2895f729 136 //DEBUG(" p5=AIN6 0x%04X %f,", adcE.read_u16(), adcE.read() );
prussell 25:1c6c2895f729 137 //DEBUG(" p6=AIN7 0x%04X %f,", adcF.read_u16(), adcF.read() );
prussell 22:533275e76f55 138 DEBUG(" \n");
prussell 22:533275e76f55 139 }
prussell 22:533275e76f55 140
prussell 0:0217a862b047 141 //==========BLE==========
prussell 13:1c67c03bbf53 142 //const static char pcDeviceName[] = "bleIOv04_pr"; //Too Long for advertising with a UUID128
prussell 26:942faa4201d5 143 const static char pcDeviceName[] = "bleIOr25"; //Advertised device name (Max length depends on available space with other Advertising data)
prussell 0:0217a862b047 144 BLEDevice ble;
prussell 10:ee3a359f7d3f 145 //Pointers to services for accesses outside main()
prussell 8:f187ba55aed2 146 HeartRateService *pServiceHRM;
prussell 15:b2c8bdef2d20 147 HealthThermometerService *pServiceHTM;
prussell 15:b2c8bdef2d20 148 BatteryService *pServiceBattery;
prussell 8:f187ba55aed2 149 DeviceInformationService *pServiceDeviceInfo;
prussell 8:f187ba55aed2 150 LinkLossService *pServiceLinkLoss;
prussell 10:ee3a359f7d3f 151 //x DFUService *pServiceDFU;
prussell 10:ee3a359f7d3f 152 //x UARTService *pServiceUART; //FromApp: pServiceUART->getTXCharacteristicHandle(); //ToApp: ble.updateCharacteristicValue(pServiceUART->getRXCharacteristicHandle(), pData, uLen);
prussell 10:ee3a359f7d3f 153 //x bleIOService *pServiceIO;
prussell 3:a98203f84063 154
prussell 6:5b6fb35b4450 155 //==========UUID==========
prussell 6:5b6fb35b4450 156 //UUID Info:
prussell 5:d36bbb315e31 157 // 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 158 /* All the custom GATT based services and characteristics must use a 128 bit UUID.
prussell 5:d36bbb315e31 159 The Bluetooth_Base_UUID is: 00000000-0000-1000-8000 00805F9B34FB.
prussell 5:d36bbb315e31 160 All the 16-bit Attribute UUIDs defined in the adopted specifications use the above base.
prussell 5:d36bbb315e31 161 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 162 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 163 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 164 Latency: Refer to Core Spec V4.0, Vol 3, Part F - 3.3.1, which is "Ready by Type Request".
prussell 5:d36bbb315e31 165 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 166 There is additional 14 extra bytes over head for the custom profiles for "Ready By Type Request Method"
prussell 5:d36bbb315e31 167 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 10:ee3a359f7d3f 168 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 10:ee3a359f7d3f 169 // 16bit UUID uses: 128bit base(32 hex digits): 0000****-0000-1000-8000 00805F9B34FB (Careful to use unsigned to avoid negatives and overflows)
prussell 10:ee3a359f7d3f 170 // 32bit UUID uses: 128bit base(32 hex digits): ********-0000-1000-8000 00805F9B34FB (Careful to use unsigned to avoid negatives and overflows)
prussell 10:ee3a359f7d3f 171
prussell 10:ee3a359f7d3f 172 //UUID128 List(Only a single UUID128 can fit in advertising)
prussell 10:ee3a359f7d3f 173 //a 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, where ****==UUID16
prussell 10:ee3a359f7d3f 174 //a 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, where ****==0x180F
prussell 4:976394791d7a 175
prussell 11:7d02fe5ebea5 176 //a //UUID16 List - Advertising these required by App nRF-Toolbox:HRM&HTM // Keep list short so advertizing not over 31bytes.
prussell 10:ee3a359f7d3f 177 /*static const uint16_t uuid16_list[] = { //Service List (Pre-defined standard 16bit services)
prussell 10:ee3a359f7d3f 178 // *Order here doesn't affect order in nRF-MCP Discovery of Services
prussell 10:ee3a359f7d3f 179 //BLE_UUID_GAP UUID_GENERIC_ACCESS //0x1800 //Included by Default, DeviceName, Appearance, PreferredConnectionParam
prussell 10:ee3a359f7d3f 180 //BLE_UUID_GATT UUID_GENERIC ATTRIBUTE //0x1801 //Included by Default, ServiceChanged,
prussell 10:ee3a359f7d3f 181 GattService::UUID_HEALTH_THERMOMETER_SERVICE, //0x1809 //HTM (Might need to be first for nRF App)
prussell 10:ee3a359f7d3f 182 GattService::UUID_HEART_RATE_SERVICE, //0x180D //HRM, BodyLocation, ControlPoint
prussell 10:ee3a359f7d3f 183 GattService::UUID_DEVICE_INFORMATION_SERVICE, //0x180A //sManufacturer, sModelNumber, sSerialNumber, sHWver, sFWver, sSWver
prussell 10:ee3a359f7d3f 184 GattService::UUID_BATTERY_SERVICE, //0x180F //BatteryLevel
prussell 10:ee3a359f7d3f 185 GattService::UUID_LINK_LOSS_SERVICE, //0x1803 //LinkLoss
prussell 10:ee3a359f7d3f 186 //x GattService::UUID_DFU, //0x1530 - See UARTServiceShortUUID in BLE_API:DFUService.cpp //
prussell 10:ee3a359f7d3f 187 //x GattService::UARTService, //0x0001~0x0003 - See DFUServiceShortUUID in BLE_API:UARTService.cpp //
prussell 10:ee3a359f7d3f 188 //Possibly useful:
prussell 10:ee3a359f7d3f 189 //x GattService::UUID_ALERT_NOTIFICATION_SERVICE, //0x1811
prussell 10:ee3a359f7d3f 190 //x GattService::UUID_CURRENT_TIME_SERVICE, //0x1805
prussell 10:ee3a359f7d3f 191 //x GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, //0x1812
prussell 10:ee3a359f7d3f 192 //x GattService::UUID_IMMEDIATE_ALERT_SERVICE, //0x1802
prussell 10:ee3a359f7d3f 193 //x GattService::UUID_PHONE_ALERT_STATUS_SERVICE, //0x180E
prussell 10:ee3a359f7d3f 194 //x GattService::UUID_REFERENCE_TIME_UPDATE_SERVICE, //0x1806
prussell 10:ee3a359f7d3f 195 //x GattService::UUID_SCAN_PARAMETERS_SERVICE, //0x1813
prussell 10:ee3a359f7d3f 196 };*/
prussell 2:c77c2b06d604 197
prussell 10:ee3a359f7d3f 198 //========== bleIO - A Custom Service for Handling IO with an App (GPIO,PWM,etc.)==========
prussell 10:ee3a359f7d3f 199 //UUID128 List - Note only the single Service UUID128 can fit in the advertising
prussell 9:2d11beda333f 200
prussell 9:2d11beda333f 201 // Custom UUID128 base for this service and its characteristics (from: http://www.itu.int/ITU-T/asn1/uuid.html)
prussell 9:2d11beda333f 202 // **This is a temporary UUID for testing by anyone, should be replaced before proceeding to real product.**
prussell 9:2d11beda333f 203 // Can check that UUID is correctly entered by viewing with Android App: nRF-Master Control panel
prussell 9:2d11beda333f 204 // UUID128 can be generated using: http://www.itu.int/ITU-T/asn1/uuid.html
prussell 9:2d11beda333f 205 // 20141218PR: [4d3281c0-86d1-11e4-b084-0002a5d5c51b] == OID[2.25.102612802202735078710424021169255859483]
prussell 10:ee3a359f7d3f 206 // Base UUID128 (1 digit modified):{0x4d,0x32,0x81,0xc0,0x86,0xd1,0x11,0xe4,0xb0,0x84,0x00,0x02,0xa5,0xd5,0xc5,0x1*};// NormalOrder
prussell 10:ee3a359f7d3f 207 uint8_t puUUID128_IOService[16] = {0x4d,0x32,0x81,0xc0,0x86,0xd1,0x11,0xe4,0xb0,0x84,0x00,0x02,0xa5,0xd5,0xc5,0x10};// Service UUID
prussell 11:7d02fe5ebea5 208 uint8_t puUUID128_IOAdvertise[16]= {0x10,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Advertising Service UUID (=ReversedOrder)
prussell 10:ee3a359f7d3f 209 // Characteristic UUID: Initially using generic blocks of IO data that may be manually dividied up into Buttons, LEDs, PWM, ADC, etc.
prussell 10:ee3a359f7d3f 210 uint8_t puUUID128_IOw8[16] = {0x4d,0x32,0x81,0xc0,0x86,0xd1,0x11,0xe4,0xb0,0x84,0x00,0x02,0xa5,0xd5,0xc5,0x11};// Write[8byte] to mbed from phone
prussell 10:ee3a359f7d3f 211 uint8_t puUUID128_IOr4[16] = {0x4d,0x32,0x81,0xc0,0x86,0xd1,0x11,0xe4,0xb0,0x84,0x00,0x02,0xa5,0xd5,0xc5,0x12};// Read[4byte] from mbed to phone
prussell 10:ee3a359f7d3f 212 uint8_t puUUID128_IOn4[16] = {0x4d,0x32,0x81,0xc0,0x86,0xd1,0x11,0xe4,0xb0,0x84,0x00,0x02,0xa5,0xd5,0xc5,0x13};// Notify[4byte] from mbed to phone
prussell 10:ee3a359f7d3f 213 // Alternately can have a characterostic for each discrete item, such as:
prussell 10:ee3a359f7d3f 214 //a uint8_t puUUID128_bleConfig32[16] = {0x1X,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Configuration 32bits
prussell 10:ee3a359f7d3f 215 //a uint8_t puUUID128_bleOut1[16] = {0x1X,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Output 1bit
prussell 10:ee3a359f7d3f 216 //a uint8_t puUUID128_bleOutPWM100[16]= {0x1X,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Output PWM (Range 0~100%)
prussell 10:ee3a359f7d3f 217 //a uint8_t puUUID128_bleOutPWM256[16]= {0x1X,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Output PWM (256 levels, 0~255)
prussell 10:ee3a359f7d3f 218 //a uint8_t puUUID128_bleIn1[16] = {0x1X,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Input 1bit
prussell 10:ee3a359f7d3f 219 //a uint8_t puUUID128_bleInADC12[16] = {0x1X,0xc5,0xd5,0xa5,0x02,0x00,0x84,0xb0,0xe4,0x11,0xd1,0x86,0xc0,0x81,0x32,0x4d};// Input ADC 12bit
prussell 10:ee3a359f7d3f 220
prussell 10:ee3a359f7d3f 221 /* Android:
prussell 10:ee3a359f7d3f 222 //bleIO Service and Characteristics
prussell 10:ee3a359f7d3f 223 attributes.put("4d3281c0-86d1-11e4-b084-0002a5d5c51b", "bleIO base");
prussell 10:ee3a359f7d3f 224 attributes.put("4d3281c0-86d1-11e4-b084-0002a5d5c510", "bleIO Service");
prussell 10:ee3a359f7d3f 225 attributes.put("4d3281c0-86d1-11e4-b084-0002a5d5c511", "bleIO w8");
prussell 10:ee3a359f7d3f 226 attributes.put("4d3281c0-86d1-11e4-b084-0002a5d5c512", "bleIO r4");
prussell 10:ee3a359f7d3f 227 attributes.put("4d3281c0-86d1-11e4-b084-0002a5d5c513", "bleIO n4");
prussell 9:2d11beda333f 228
prussell 10:ee3a359f7d3f 229 attributes.put("1bc5d5a5-0200-84b0-e411-d186c081324d", "bleIO rev base");
prussell 10:ee3a359f7d3f 230 attributes.put("10c5d5a5-0200-84b0-e411-d186c081324d", "bleIO rev Service");
prussell 10:ee3a359f7d3f 231 attributes.put("11c5d5a5-0200-84b0-e411-d186c081324d", "bleIO rev w8");
prussell 10:ee3a359f7d3f 232 attributes.put("12c5d5a5-0200-84b0-e411-d186c081324d", "bleIO rev r4");
prussell 10:ee3a359f7d3f 233 attributes.put("13c5d5a5-0200-84b0-e411-d186c081324d", "bleIO rev n4");
prussell 10:ee3a359f7d3f 234 */
prussell 10:ee3a359f7d3f 235
prussell 10:ee3a359f7d3f 236 // Characteristic Value Storage (with Initial values, should match actual data type transferred, doesn't have to be byte array):
prussell 12:8bac5f5d3a3e 237 //a uint8_t pIOw8[8] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}; //Value Storage for Characteristic Write8
prussell 12:8bac5f5d3a3e 238 //a uint8_t pIOr4[4] = {0x20,0x21,0x22,0x23}; //Value Storage for Characteristic Read4
prussell 12:8bac5f5d3a3e 239 //a uint8_t pIOn4[4] = {0x30,0x31,0x32,0x33}; //Value Storage for Characteristic Notify4
prussell 12:8bac5f5d3a3e 240
prussell 12:8bac5f5d3a3e 241 union { // Option: split long setup from short updates to minimize BLE power and traffic
prussell 12:8bac5f5d3a3e 242 struct {// First item in union defines the initializers
prussell 12:8bac5f5d3a3e 243 uint8_t L1pwm100; // LED1 Brightness (0%~100%)
prussell 12:8bac5f5d3a3e 244 uint8_t L2pwm255; // LED2 Brightness (0~255)
prussell 12:8bac5f5d3a3e 245 //float xxxx; //Option: If both smartphone and device use same type of float, else put converter in smartphone code (phone has larger battery and memory)
prussell 12:8bac5f5d3a3e 246 uint16_t px[3]; // Spare 3*16bit (Test: incremented by Ticker1
prussell 12:8bac5f5d3a3e 247 } s;
prussell 12:8bac5f5d3a3e 248 uint8_t pu[]; //Direct Byte access
prussell 12:8bac5f5d3a3e 249 char pc[]; //Character Access (No Terminating Null)
prussell 12:8bac5f5d3a3e 250 } sIOw8 = {100,255,0xA00A, 0xB000, 0xC000}; // Structure/union for Characteristic IOw8
prussell 12:8bac5f5d3a3e 251 // sIOw8.s.L1pwm100, sIOw8.s.L2pwm255, sIOw8.s.px, sIOw8.pu
prussell 12:8bac5f5d3a3e 252
prussell 12:8bac5f5d3a3e 253 union { // Longer maybe OK since only read upon command
prussell 12:8bac5f5d3a3e 254 struct {// First item in union defines the initializers
prussell 12:8bac5f5d3a3e 255 uint8_t bB1p:1,bB2p:1; // Button status, 1/true=Pressed, bit1==Button1, bit2==Button2
prussell 12:8bac5f5d3a3e 256 uint8_t uB1p:6; // Count Button1 Presses (6bit)
prussell 12:8bac5f5d3a3e 257 uint8_t uB1r; // Count Button1 Releases
prussell 12:8bac5f5d3a3e 258 uint8_t uB2p; // Count Button2 Presses
prussell 12:8bac5f5d3a3e 259 uint8_t uB2r; // Count Button2 Releases
prussell 12:8bac5f5d3a3e 260 // // Option: ADC or other inputs or device status
prussell 12:8bac5f5d3a3e 261 } s;
prussell 12:8bac5f5d3a3e 262 uint8_t pu[]; //Direct Byte access
prussell 12:8bac5f5d3a3e 263 char pc[]; //Character Access (No Terminating Null)
prussell 12:8bac5f5d3a3e 264 } sIOr4 = { true, false, 0x3F, 255, 255, 255}; // Structure/union for Characteristic IOr4
prussell 12:8bac5f5d3a3e 265 // sIOr4.s.bB1p, sIOr4.s.bB1p, sIOr4.s.uB1p, sIOr4.s.bB1r, sIOr4.s.uB2p, sIOr4.s.uB2r, sIOr4.pu
prussell 12:8bac5f5d3a3e 266
prussell 12:8bac5f5d3a3e 267 union { // Option: Shorten content to reduce BLE power and traffic
prussell 12:8bac5f5d3a3e 268 struct {// First item in union defines the initializers
prussell 12:8bac5f5d3a3e 269 uint8_t bB1p:1,bB2p:1; // Button status, 1/true=Pressed, bit1==Button1, bit2==Button2
prussell 12:8bac5f5d3a3e 270 uint8_t uB1p:6; // Count Button2 Presses (6bit) *Notify*
prussell 12:8bac5f5d3a3e 271 uint8_t uB2r; // Count Button2 Releases *Notify*
prussell 12:8bac5f5d3a3e 272 int16_t iTempC100; // Temperature in hundreths of 'C (i.e. float = iTempC10/100)
prussell 12:8bac5f5d3a3e 273 // // Option: ADC or other inputs or device status
prussell 12:8bac5f5d3a3e 274 } s;
prussell 12:8bac5f5d3a3e 275 uint8_t pu[]; //Direct Byte access
prussell 12:8bac5f5d3a3e 276 char pc[]; //Character Access (No Terminating Null)
prussell 12:8bac5f5d3a3e 277 } sIOn4 = { false, true, 0x3F, 255, -2345/*=-23.45'C*/}; // Structure/union for Characteristic IOn4
prussell 12:8bac5f5d3a3e 278 // sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, sIOn4.s.iTempC100, sIOn4.pu
prussell 9:2d11beda333f 279
prussell 9:2d11beda333f 280 //x GattCharacteristic::GattAttribute *descriptors[]; //How Set Characteristic Descriptors? Maybe in the App is easier?
prussell 9:2d11beda333f 281
prussell 10:ee3a359f7d3f 282 //IO Characteristics: //GattCharacteristics xx(*UUID, *Payload=*Value, LenInit, LenMax, Properties)
prussell 18:c676e79d5d3e 283 //GattCharacteristic IOw8(puUUID128_IOw8, sIOw8.pu, sizeof(sIOw8), sizeof(sIOw8), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
prussell 12:8bac5f5d3a3e 284 GattCharacteristic IOw8(puUUID128_IOw8, sIOw8.pu, sizeof(sIOw8), sizeof(sIOw8), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);// Allow Host to read back last setting
prussell 18:c676e79d5d3e 285 GattCharacteristic IOr4(puUUID128_IOr4, sIOr4.pu, sizeof(sIOr4), sizeof(sIOr4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); // Host can manually request
prussell 19:ebe7b59d9c76 286 GattCharacteristic IOn4(puUUID128_IOn4, sIOn4.pu, sizeof(sIOn4), sizeof(sIOn4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);// Host is Notified of changes (Same as HRM), *Works but first read not until a channge
prussell 19:ebe7b59d9c76 287 //GattCharacteristic IOn4(puUUID128_IOn4, sIOn4.pu, sizeof(sIOn4), sizeof(sIOn4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); // Host is notified of changes (Same as HTM & BattLevel), Buggy until can queue BLE Operations
prussell 12:8bac5f5d3a3e 288 GattCharacteristic *pCustomCharacteristics[] = {&IOw8, &IOr4, &IOn4};//Table of Pointers to GattCharacteristics
prussell 10:ee3a359f7d3f 289
prussell 10:ee3a359f7d3f 290 //IO Service: //GattService::GattService(*UUID, *GattCharacteristics, (numCharacteristics) ) :
prussell 10:ee3a359f7d3f 291 GattService ServiceIO(puUUID128_IOService, pCustomCharacteristics, (sizeof(pCustomCharacteristics)/sizeof(pCustomCharacteristics[0])));
prussell 10:ee3a359f7d3f 292 GattService *pServiceIO= &ServiceIO; // Pointer to Service
prussell 9:2d11beda333f 293
prussell 12:8bac5f5d3a3e 294 //========== Functions for IO Characteristics ========
prussell 12:8bac5f5d3a3e 295 void vShowIO(void)
prussell 12:8bac5f5d3a3e 296 { //TODO: For Read Characteristics get data actually written to Characteristic, versus the memory expected to be in characteristic.
prussell 12:8bac5f5d3a3e 297 uint8_t puBuf8[8];
prussell 12:8bac5f5d3a3e 298 uint16_t uLen;
prussell 12:8bac5f5d3a3e 299
prussell 12:8bac5f5d3a3e 300 DEBUG(" ShowIO:\n");
prussell 12:8bac5f5d3a3e 301
prussell 25:1c6c2895f729 302 // IOw8 Write (Displaying structure and buffer(c) data for comparison)
prussell 16:3e83f2babdfb 303 uLen=sizeof(puBuf8); ble.readCharacteristicValue(IOw8.getValueHandle(), puBuf8, &uLen); // Real Characteristic's Actual Value
prussell 25:1c6c2895f729 304 //DEBUG(" sIOw8: Handle:%d Len:%d L1:%d L2:%d %04X %04X %04X\n", IOw8.getValueHandle(), uLen, sIOw8.s.L1pwm100, sIOw8.s.L2pwm255, sIOw8.s.px[0], sIOw8.s.px[1], sIOw8.s.px[2]);
prussell 25:1c6c2895f729 305 //DEBUG(" sIOw8: Handle:%d Len:%d [%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), sizeof(sIOw8), sIOw8.pu[0],sIOw8.pu[1],sIOw8.pu[2],sIOw8.pu[3],sIOw8.pu[4],sIOw8.pu[5],sIOw8.pu[6],sIOw8.pu[7]);
prussell 25:1c6c2895f729 306 //DEBUG(" cIOw8: Handle:%d Len:%d [%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3], puBuf8[4], puBuf8[5], puBuf8[6], puBuf8[7] );
prussell 25:1c6c2895f729 307 DEBUG(" sIOw8: Handle:%d Len:%d L1:%d L2:%d %04X %04X %04X", IOw8.getValueHandle(), uLen, sIOw8.s.L1pwm100, sIOw8.s.L2pwm255, sIOw8.s.px[0], sIOw8.s.px[1], sIOw8.s.px[2]);
prussell 25:1c6c2895f729 308 DEBUG(" sIOw8:[%02X %02X %02X %02X %02X %02X %02X %02X]", IOw8.getValueHandle(), sizeof(sIOw8), sIOw8.pu[0],sIOw8.pu[1],sIOw8.pu[2],sIOw8.pu[3],sIOw8.pu[4],sIOw8.pu[5],sIOw8.pu[6],sIOw8.pu[7]);
prussell 25:1c6c2895f729 309 DEBUG(" cIOw8:[%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3], puBuf8[4], puBuf8[5], puBuf8[6], puBuf8[7] );
prussell 12:8bac5f5d3a3e 310
prussell 25:1c6c2895f729 311 // IOr4 Read (Displaying structure and buffer(c) data for comparison)
prussell 16:3e83f2babdfb 312 uLen=sizeof(puBuf8); ble.readCharacteristicValue(IOr4.getValueHandle(), puBuf8, &uLen); // Real Characteristic's Actual Value
prussell 25:1c6c2895f729 313 //DEBUG("\n sIOr4: Handle:%d Len:%d B1:%d B2:%d B1p:%d B1r:%d B2p:%d B2r:%d\n", IOr4.getValueHandle(), uLen, sIOr4.s.bB1p, sIOr4.s.bB2p, sIOr4.s.uB1p, sIOr4.s.uB1r, sIOr4.s.uB2p, sIOr4.s.uB2r);
prussell 25:1c6c2895f729 314 //DEBUG(" sIOr4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOr4.getValueHandle(), sizeof(sIOr4), sIOr4.pu[0], sIOr4.pu[1], sIOr4.pu[2], sIOr4.pu[3]);
prussell 25:1c6c2895f729 315 //DEBUG(" cIOr4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOr4.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3] );
prussell 25:1c6c2895f729 316 DEBUG(" sIOr4: Handle:%d Len:%d B1:%d B2:%d B1p:%d B1r:%d B2p:%d B2r:%d", IOr4.getValueHandle(), uLen, sIOr4.s.bB1p, sIOr4.s.bB2p, sIOr4.s.uB1p, sIOr4.s.uB1r, sIOr4.s.uB2p, sIOr4.s.uB2r);
prussell 25:1c6c2895f729 317 DEBUG(" sIOr4:[%02X %02X %02X %02X]", IOr4.getValueHandle(), sizeof(sIOr4), sIOr4.pu[0], sIOr4.pu[1], sIOr4.pu[2], sIOr4.pu[3]);
prussell 25:1c6c2895f729 318 DEBUG(" cIOr4:[%02X %02X %02X %02X]\n", IOr4.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3] );
prussell 12:8bac5f5d3a3e 319
prussell 25:1c6c2895f729 320 // IOn4 Notify (Displaying structure and buffer(c) data for comparison)
prussell 16:3e83f2babdfb 321 uLen=sizeof(puBuf8); ble.readCharacteristicValue(IOn4.getValueHandle(), puBuf8, &uLen); // Real Characteristic's Actual Value
prussell 25:1c6c2895f729 322 //DEBUG("\n sIOn4: Handle:%d Len:%d B1:%d B2:%d B1p:%d B2r:%d %.2f\n", IOn4.getValueHandle(), uLen, sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, ((float)sIOn4.s.iTempC100/100.0));
prussell 25:1c6c2895f729 323 //DEBUG(" sIOn4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOn4.getValueHandle(), sizeof(sIOn4), sIOn4.pu[0], sIOn4.pu[1], sIOn4.pu[2], sIOn4.pu[3]);
prussell 25:1c6c2895f729 324 //DEBUG(" cIOn4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOn4.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3] );
prussell 25:1c6c2895f729 325 DEBUG(" sIOn4: Handle:%d Len:%d B1:%d B2:%d B1p:%d B2r:%d %.2f", IOn4.getValueHandle(), uLen, sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, ((float)sIOn4.s.iTempC100/100.0));
prussell 25:1c6c2895f729 326 DEBUG(" sIOn4:[%02X %02X %02X %02X]", IOn4.getValueHandle(), sizeof(sIOn4), sIOn4.pu[0], sIOn4.pu[1], sIOn4.pu[2], sIOn4.pu[3]);
prussell 25:1c6c2895f729 327 DEBUG(" cIOn4:[%02X %02X %02X %02X]\n", IOn4.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3] );
prussell 15:b2c8bdef2d20 328
prussell 15:b2c8bdef2d20 329 //DEBUG("\n Handles for Standard Services' Characteristics:\n");
prussell 15:b2c8bdef2d20 330 //DEBUG(" HRM: Rate:%d Location:%d Control:%d", pServiceHRM->getCharacteristic(0)->getValueHandle(),pServiceHRM->getCharacteristic(1)->getValueHandle(),pServiceHRM->getCharacteristic(2)->getValueHandle());
prussell 15:b2c8bdef2d20 331 //DEBUG(" HTM: Temp:%d Type:%d", pServiceHTM->getCharacteristic(0)->getValueHandle(),pServiceHTM->getCharacteristic(1)->getValueHandle());
prussell 15:b2c8bdef2d20 332 //DEBUG(" Batt: Level:%d", pServiceBattery->getCharacteristic(0)->getHandle());
prussell 15:b2c8bdef2d20 333 //DEBUG(" DeviceInfo: %d~%d", pServiceDeviceInfo->getCharacteristic(0)->getHandle(), pServiceDeviceInfo->getCharacteristic(5)->getHandle());
prussell 15:b2c8bdef2d20 334 //DEBUG(" LinkLoss: AlertLevel:%d", pServiceLinkLoss->getCharacteristic(0)->getHandle());
prussell 15:b2c8bdef2d20 335 //DEBUG(" DFU:%d", pServiceDFU.getValueAttribute().getHandle());
prussell 15:b2c8bdef2d20 336 //DEBUG(" UART:%d\n", pServiceUART.getValueAttribute().getHandle());
prussell 22:533275e76f55 337
prussell 22:533275e76f55 338 vShowADC();
prussell 12:8bac5f5d3a3e 339 }
prussell 12:8bac5f5d3a3e 340
prussell 12:8bac5f5d3a3e 341 //==== Soft Updates to Characteristics for initial tests: (Most replaced by real buttons/sensors/timers )
prussell 10:ee3a359f7d3f 342 /*void vUpdate_IOw8(void) // Handle in device changes to w8 characteristic
prussell 12:8bac5f5d3a3e 343 {//a Option: Allow device to modify its settings and inform host (Some devices may be able to self-modify host written settings)
prussell 10:ee3a359f7d3f 344 static uint8_t uw8; //Level: 0..2
prussell 10:ee3a359f7d3f 345 switch(++uw8){
prussell 10:ee3a359f7d3f 346 case 2: memcpy(pIOw8, "w2w2w2wc", sizeof(pIOw8)); DEBUG(" w8c"); break;
prussell 10:ee3a359f7d3f 347 case 1: memcpy(pIOw8, "w1w1w1wb", sizeof(pIOw8)); DEBUG(" w8b"); break;
prussell 10:ee3a359f7d3f 348 default: uw8=0; memcpy(pIOw8, "w0w0w0wa", sizeof(pIOw8)); DEBUG(" w8a"); break;
prussell 9:2d11beda333f 349 }
prussell 10:ee3a359f7d3f 350 //ble.updateCharacteristicValue(uint16_t handle, const uint8_t *value, uint16_t size, bool localOnly)
prussell 10:ee3a359f7d3f 351 ble.updateCharacteristicValue(IOw8.getValueHandle(), pIOw8, sizeof(pIOw8));
prussell 9:2d11beda333f 352 //pServiceHRM->updateHeartRate( u8_hrm );// Update Characteristic so sent by BLE
prussell 12:8bac5f5d3a3e 353 vShowIO();
prussell 10:ee3a359f7d3f 354 }*/
prussell 10:ee3a359f7d3f 355
prussell 12:8bac5f5d3a3e 356 //==== Hard Updates to Characteristics: [onButton()] Notify: B1press or B2release
prussell 12:8bac5f5d3a3e 357 // *When direct driving hardware consider adjusting drive within the onCallback to reduce response time
prussell 12:8bac5f5d3a3e 358 //TODO: Check need of volatile for changes in interrupts affecting variables in non-interrupt code?
prussell 12:8bac5f5d3a3e 359
prussell 12:8bac5f5d3a3e 360 volatile uint8_t uB1press; // Events since last handled in main()
prussell 12:8bac5f5d3a3e 361 volatile uint8_t uB1release;// Events since last handled in main()
prussell 12:8bac5f5d3a3e 362 volatile uint8_t uB2press; // Events since last handled in main()
prussell 12:8bac5f5d3a3e 363 volatile uint8_t uB2release;// Events since last handled in main()
prussell 12:8bac5f5d3a3e 364
prussell 12:8bac5f5d3a3e 365 void vFillIO(void) // Fill the structures for the Characteristics, but leave any Notify to calling function
prussell 12:8bac5f5d3a3e 366 { //Structures are filled completely so available for BLE read at any time
prussell 12:8bac5f5d3a3e 367 // sIOr4.s.bB1p, sIOr4.s.bB1p, sIOr4.s.uB1p, sIOr4.s.bB1r, sIOr4.s.uB2p, sIOr4.s.uB2r, sIOr4.pu
prussell 12:8bac5f5d3a3e 368 sIOr4.s.bB1p = !bB1in; //Button1 Pressed (nRF51822 mkit: Pressed=Lo)
prussell 12:8bac5f5d3a3e 369 sIOr4.s.bB2p = !bB2in; //Button2 Pressed (nRF51822 mkit: Pressed=Lo)
prussell 12:8bac5f5d3a3e 370 sIOr4.s.uB1p = uB1press;// Button1 Presses (Truncates to size)
prussell 12:8bac5f5d3a3e 371 sIOr4.s.uB1r = uB1release;
prussell 12:8bac5f5d3a3e 372 sIOr4.s.uB2p = uB2press;
prussell 12:8bac5f5d3a3e 373 sIOr4.s.uB2r = uB2release;
prussell 12:8bac5f5d3a3e 374
prussell 12:8bac5f5d3a3e 375 // sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, sIOn4.s.iTempC100, sIOn4.pu
prussell 12:8bac5f5d3a3e 376 sIOn4.s.bB1p = !bB1in; //Button1 Pressed (nRF51822 mkit: Pressed=Lo)
prussell 12:8bac5f5d3a3e 377 sIOn4.s.bB2p = !bB2in; //Button2 Pressed (nRF51822 mkit: Pressed=Lo)
prussell 12:8bac5f5d3a3e 378 sIOn4.s.uB1p = uB1press;//Button1 Presses (Truncates to size)
prussell 12:8bac5f5d3a3e 379 sIOn4.s.uB2r = uB2release;
prussell 12:8bac5f5d3a3e 380
prussell 12:8bac5f5d3a3e 381 int32_t i32_C_nRF; sd_temp_get(&i32_C_nRF); //Read the nRF Internal Temperature (Die in 0.25'C steps, offset +16'C)
prussell 12:8bac5f5d3a3e 382 sIOn4.s.iTempC100 = (i32_C_nRF*25)-(1600); //Save temperature in hundreths (0.01'C steps relative to 0'C)(.25'C * 25=.01'C steps)
prussell 12:8bac5f5d3a3e 383 //float fTemperature = (float(i32_temp)/4.0) - 16.0; // Scale&Shift (0.25'C from -16'C?)
prussell 20:fb286f736dc4 384
prussell 20:fb286f736dc4 385 ble.updateCharacteristicValue(IOr4.getValueHandle(), sIOr4.pu, sizeof(sIOr4)); // Update r4 data so ready for read (Doesn't Trigger Notify)
prussell 9:2d11beda333f 386 }
prussell 9:2d11beda333f 387
prussell 23:78aad4e53ae2 388 //PR: Notify: Doing Notify on both Press and Release since n4 contains status of multiple inputs so need both bits to be correct. If Notify Characteristic is single button then notify could be on just press or just release.
prussell 12:8bac5f5d3a3e 389 void onB1press(void) // B1 Press == *Notify*
prussell 12:8bac5f5d3a3e 390 { // Update Characteristics that include this button
prussell 12:8bac5f5d3a3e 391 uB1press++; // Flag/Count Events (allows detect any missed processing)
prussell 12:8bac5f5d3a3e 392 vFillIO(); // Prepare IO Characteristic data
prussell 20:fb286f736dc4 393 ble.updateCharacteristicValue(IOn4.getValueHandle(), sIOn4.pu, sizeof(sIOn4));// Triggers Notify (Reading n4 at other times may have old data)
prussell 12:8bac5f5d3a3e 394 DEBUG("\n B1p%d", uB1press); vShowIO();
prussell 12:8bac5f5d3a3e 395 };
prussell 12:8bac5f5d3a3e 396 void onB1release(void) // B1 Release
prussell 12:8bac5f5d3a3e 397 { // Update Characteristics that include this button
prussell 12:8bac5f5d3a3e 398 uB1release++; // Flag/Count Events (allows detect any missed processing)
prussell 12:8bac5f5d3a3e 399 vFillIO(); // Prepare IO Characteristic data
prussell 20:fb286f736dc4 400 ble.updateCharacteristicValue(IOn4.getValueHandle(), sIOn4.pu, sizeof(sIOn4));// Triggers Notify (Reading n4 at other times may have old data)
prussell 12:8bac5f5d3a3e 401 DEBUG("\n B1r%d", uB1release); vShowIO();
prussell 12:8bac5f5d3a3e 402 };
prussell 12:8bac5f5d3a3e 403 void onB2press(void) // B2 Press
prussell 12:8bac5f5d3a3e 404 { // Update Characteristics that include this button
prussell 12:8bac5f5d3a3e 405 uB2press++; // Flag/Count Events (allows detect any missed processing)
prussell 12:8bac5f5d3a3e 406 vFillIO(); // Prepare IO Characteristic data
prussell 20:fb286f736dc4 407 ble.updateCharacteristicValue(IOn4.getValueHandle(), sIOn4.pu, sizeof(sIOn4));// Triggers Notify (Reading n4 at other times may have old data)
prussell 12:8bac5f5d3a3e 408 DEBUG("\n B2p%d", uB2press); vShowIO();
prussell 12:8bac5f5d3a3e 409 };
prussell 12:8bac5f5d3a3e 410 void onB2release(void) // B2 Release
prussell 12:8bac5f5d3a3e 411 { // Update Characteristics that include this button
prussell 12:8bac5f5d3a3e 412 uB2release++; // Flag/Count Events (allows detect any missed processing)
prussell 12:8bac5f5d3a3e 413 vFillIO(); // Prepare IO Characteristic data
prussell 20:fb286f736dc4 414 ble.updateCharacteristicValue(IOn4.getValueHandle(), sIOn4.pu, sizeof(sIOn4));// Triggers Notify (Reading n4 at other times may have old data)
prussell 12:8bac5f5d3a3e 415 DEBUG("\n B2r%d", uB2release); vShowIO();
prussell 12:8bac5f5d3a3e 416 };
prussell 9:2d11beda333f 417
prussell 0:0217a862b047 418 //==========Functions:BLE==========
prussell 0:0217a862b047 419 void Callback_BLE_onTimeout(void)
prussell 10:ee3a359f7d3f 420 { //PR: Haven't seen this, even when phone moved out of range and events occur like OnDisconnect(Reason0x08) or LinkLoss
prussell 12:8bac5f5d3a3e 421 DEBUG("\n\n\n\n**** BLEi: Callback_BLE_onTimeout() ****\n\n\n\n" );
prussell 0:0217a862b047 422
prussell 0:0217a862b047 423 //DEBUG("\nBLE:Callback_BLE_onTimeout(), Restarting Advertising\n" );
prussell 0:0217a862b047 424 //ble.startAdvertising();
prussell 0:0217a862b047 425 }
prussell 0:0217a862b047 426
prussell 0:0217a862b047 427 void Callback_BLE_onDisconnect(Gap::Handle_t tHandle, Gap::DisconnectionReason_t eReason)
prussell 10:ee3a359f7d3f 428 { //PR: onDisconnect(Reason:8) occured after ~20Tx with no onDataSent() after phone moved out of range
prussell 0:0217a862b047 429
prussell 23:78aad4e53ae2 430
prussell 0:0217a862b047 431 // REMOTE_USER_TERMINATED_CONNECTION = 0x13 = 19,
prussell 0:0217a862b047 432 // LOCAL_HOST_TERMINATED_CONNECTION = 0x16 = 22,
prussell 0:0217a862b047 433 // CONN_INTERVAL_UNACCEPTABLE = 0x3B = 59,
prussell 23:78aad4e53ae2 434 DEBUG("\nBLEi: Callback_BLE_Disconnect(Handle:%d, eReason:0x%02x=", tHandle, eReason );//PR: Occurs properly when click disconnect in App nRFToolbox:HRM
prussell 23:78aad4e53ae2 435 switch(eReason) {
prussell 23:78aad4e53ae2 436 case Gap::REMOTE_USER_TERMINATED_CONNECTION: DEBUG("REMOTE_USER_TERMINATED_CONNECTION"); break;
prussell 23:78aad4e53ae2 437 case Gap::CONN_INTERVAL_UNACCEPTABLE: DEBUG("CONN_INTERVAL_UNACCEPTABLE"); break;
prussell 23:78aad4e53ae2 438 case Gap::LOCAL_HOST_TERMINATED_CONNECTION: DEBUG("LOCAL_HOST_TERMINATED_CONNECTION"); break;
prussell 23:78aad4e53ae2 439 default: DEBUG("UNKNOWN"); break;
prussell 23:78aad4e53ae2 440 }
prussell 23:78aad4e53ae2 441 DEBUG("), Restarting Advertising\n", tHandle, eReason );//PR: Occurs properly when click disconnect in App nRFToolbox:HRM
prussell 0:0217a862b047 442
prussell 0:0217a862b047 443 //DEBUG("Wait10sec...\n");wait(10.0); //PR: Optional to test effect on advertising
prussell 0:0217a862b047 444 ble.startAdvertising(); // restart advertising
prussell 23:78aad4e53ae2 445
prussell 23:78aad4e53ae2 446 //TODO: LED Mode to Indicate Advertising until something else changes LED Mode?
prussell 0:0217a862b047 447 }
prussell 0:0217a862b047 448
prussell 23:78aad4e53ae2 449
prussell 0:0217a862b047 450 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 451 {
prussell 0:0217a862b047 452 DEBUG("\nBLEi: Callback_BLE_Connect(Handle:%d, eType:%d, Add:%u ...)\n", tHandle, ePeerAddrType, c6PeerAddr);
prussell 0:0217a862b047 453
prussell 11:7d02fe5ebea5 454 //x #if ENABLE_BLE_SLOW //UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL //PR: Adopted optional code never tested
prussell 11:7d02fe5ebea5 455 //x // Updating connection parameters can be attempted only after a connection has been
prussell 11:7d02fe5ebea5 456 //x // established. Please note that the ble-Central is still the final arbiter for
prussell 11:7d02fe5ebea5 457 //x // the effective parameters; the peripheral can only hope that the request is
prussell 11:7d02fe5ebea5 458 //x // honored. Please also be mindful of the constraints that might be enforced by
prussell 11:7d02fe5ebea5 459 //x // the BLE stack on the underlying controller.
prussell 11:7d02fe5ebea5 460 //x #define MIN_CONN_INTERVAL 250 // Minimum connection interval (250 ms)
prussell 11:7d02fe5ebea5 461 //x #define MAX_CONN_INTERVAL 350 // Maximum connection interval (350 ms)
prussell 11:7d02fe5ebea5 462 //x #define CONN_SUP_TIMEOUT 6000 // Connection supervisory timeout (6 seconds)
prussell 11:7d02fe5ebea5 463 //x #define SLAVE_LATENCY 4
prussell 11:7d02fe5ebea5 464 //x Gap::ConnectionParams_t tGap_conn_params;
prussell 11:7d02fe5ebea5 465 //x tGap_conn_params.minConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(MIN_CONN_INTERVAL);
prussell 11:7d02fe5ebea5 466 //x tGap_conn_params.maxConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(MAX_CONN_INTERVAL);
prussell 11:7d02fe5ebea5 467 //x tGap_conn_params.connectionSupervisionTimeout = Gap::MSEC_TO_GAP_DURATION_UNITS(CONN_SUP_TIMEOUT);
prussell 11:7d02fe5ebea5 468 //x tGap_conn_params.slaveLatency = SLAVE_LATENCY;
prussell 11:7d02fe5ebea5 469 //x ble.updateConnectionParams(tHandle, &tGap_conn_params);
prussell 11:7d02fe5ebea5 470 //x #endif // #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL
prussell 0:0217a862b047 471 }
prussell 0:0217a862b047 472
prussell 25:1c6c2895f729 473 #ifdef NOT_DEFINED //Not available in BLE_API r277 20150126
prussell 23:78aad4e53ae2 474 void Callback_BLE_onDataRead(const GattCharacteristicReadAuthCBParams *pParams) //NotAvailableOnlineYet20150114
prussell 23:78aad4e53ae2 475 {
prussell 23:78aad4e53ae2 476 GattAttribute::Handle_t tHandle=pParams->charHandle;
prussell 23:78aad4e53ae2 477
prussell 23:78aad4e53ae2 478 //Handle Changes to Service Characteristics:
prussell 23:78aad4e53ae2 479 if(!ble.getGapState().connected){ //Ensure BLE still connected
prussell 25:1c6c2895f729 480 DEBUG("\nBLEi: Callback_BLE_onDataRead() while disconnected!!");
prussell 23:78aad4e53ae2 481 } else if (tHandle == IOr4.getValueHandle()) { // IOr4 Characteristic?
prussell 25:1c6c2895f729 482 DEBUG("\nBLEi: Callback_BLE_onDataRead() while disconnected!!");
prussell 23:78aad4e53ae2 483 vFillIO(); // Update the data for this Characteristic
prussell 23:78aad4e53ae2 484 vShowIO();
prussell 23:78aad4e53ae2 485 //} else if (tHandle == IOw8.getValueHandle()) { // Writeonly, Continue with no changes, App can read back whatever was last written
prussell 23:78aad4e53ae2 486 //} else if (tHandle == IOr4.getValueHandle()) { // Notifyonly, shouldn't occur, is automatically sent when Notify changes, anything needed should be in IOr4
prussell 23:78aad4e53ae2 487 } else {
prussell 25:1c6c2895f729 488 DEBUG("\nBLEi: Callback_BLE_onDataRead(Unknown tHandle:%d)\n\n", tHandle);
prussell 23:78aad4e53ae2 489 }
prussell 23:78aad4e53ae2 490 }
prussell 25:1c6c2895f729 491 #endif
prussell 23:78aad4e53ae2 492
prussell 12:8bac5f5d3a3e 493 static volatile bool bNotifySent = false; //Volatile, don't optimize, changes under interrupt control
prussell 12:8bac5f5d3a3e 494 static volatile unsigned uNotifyBLE;
prussell 12:8bac5f5d3a3e 495 void Callback_BLE_onNotifySent(unsigned uNotify) //TODO: Consider renaming to onNotifySent(uNotified)
prussell 12:8bac5f5d3a3e 496 { // Appears to get called when a Characteristic flagged for Notify is Updated/Sent (not for a characteristic being Read by the app).
prussell 12:8bac5f5d3a3e 497 uNotifyBLE=uNotify;
prussell 12:8bac5f5d3a3e 498 DEBUG(" Senti(%u)", uNotifyBLE); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
prussell 12:8bac5f5d3a3e 499 bNotifySent = true;
prussell 0:0217a862b047 500 }
prussell 0:0217a862b047 501
prussell 0:0217a862b047 502 void Callback_BLE_onDataWritten(const GattCharacteristicWriteCBParams *pParams)
prussell 9:2d11beda333f 503 { // This occurs when use nRF-MCP to save a new Characteristic Value (SingleUpASrrowIcon) such as New Heart Rate Control Point (unsent if incorrect length)
prussell 9:2d11beda333f 504 GattAttribute::Handle_t tHandle=pParams->charHandle;
prussell 23:78aad4e53ae2 505 uint16_t uLen;
prussell 0:0217a862b047 506
prussell 0:0217a862b047 507 //Warning: *data may not be NULL terminated
prussell 9:2d11beda333f 508 DEBUG("\nBLEi: Callback_BLE_onDataWritten(Handle:%d, eOp:%d, uOffset:%u uLen:%u Data0[0x%02x]=Data[%*s]\n", tHandle, pParams->op, pParams->offset, pParams->len, (char)(pParams->data[0]), pParams->len, pParams->data);
prussell 9:2d11beda333f 509
prussell 10:ee3a359f7d3f 510 /* //TODO: Add check of op type with tHandle check: switch(pParams->op){ case: GATTS_CHAR_OP_WRITE_REQ:}...
prussell 10:ee3a359f7d3f 511 switch(pParams->op){
prussell 10:ee3a359f7d3f 512 case GATTS_CHAR_OP_INVALID:
prussell 10:ee3a359f7d3f 513 case GATTS_CHAR_OP_WRITE_REQ
prussell 10:ee3a359f7d3f 514 case GATTS_CHAR_OP_WRITE_CMD
prussell 10:ee3a359f7d3f 515 case GATTS_CHAR_OP_SIGN_WRITE_CMD //< Signed Write Command
prussell 10:ee3a359f7d3f 516 case GATTS_CHAR_OP_PREP_WRITE_REQ //< Prepare Write Request
prussell 10:ee3a359f7d3f 517 case GATTS_CHAR_OP_EXEC_WRITE_REQ_CANCEL //< Execute Write Request: Cancel all prepared writes
prussell 10:ee3a359f7d3f 518 case GATTS_CHAR_OP_EXEC_WRITE_REQ_NOW //< Execute Write Request: Immediately execute all prepared writes
prussell 10:ee3a359f7d3f 519 default: Error?
prussell 10:ee3a359f7d3f 520 }*/
prussell 9:2d11beda333f 521
prussell 10:ee3a359f7d3f 522 //a These are equivalent ways of accessing characteristic handles:
prussell 10:ee3a359f7d3f 523 //a if (pParams->charHandle == IOw8.getValueHandle()) { DEBUG("\n\nOK tHandle %d\n\n", pParams->charHandle); }
prussell 10:ee3a359f7d3f 524 //a if (pParams->charHandle == ServiceIO.getCharacteristic(0)->getValueHandle()) { DEBUG("\n\nOK tHandle %d\n\n", pParams->charHandle); }
prussell 10:ee3a359f7d3f 525 //a if (IOw8.getValueHandle() == ServiceIO.getCharacteristic(0)->getValueHandle()) { DEBUG("\n\nOK tHandle equivalent %d\n\n", pParams->charHandle); }
prussell 9:2d11beda333f 526
prussell 9:2d11beda333f 527 //Handle Changes to Service Characteristics:
prussell 10:ee3a359f7d3f 528 if(!ble.getGapState().connected){ //Ensure BLE still connected
prussell 10:ee3a359f7d3f 529 DEBUG("BLEi: Callback_BLE_onDataWritten() while disconnected!!");
prussell 23:78aad4e53ae2 530 } else if (tHandle == IOw8.getValueHandle()) { // This occurs from Write by App nRF-MCP since has Write Property set
prussell 23:78aad4e53ae2 531 ble.readCharacteristicValue(tHandle, sIOw8.pu, &uLen); //Update Characteristic with new information (Option: Verify length or a checksum first)
prussell 23:78aad4e53ae2 532 vShowIO();
prussell 23:78aad4e53ae2 533 bAppControl = true; //Host has taken control of LEDs
prussell 23:78aad4e53ae2 534 fL1level = (((float)sIOw8.s.L1pwm100)/100.0); if(fL1level>1.0){fL1level=1.0;}; fL1pwm=fL1level; //Set LED1 Level
prussell 23:78aad4e53ae2 535 fL2level = (((float)sIOw8.s.L2pwm255)/255.0); if(fL2level>1.0){fL2level=1.0;}; fL2pwm=fL2level; //Set LED1 Level
prussell 23:78aad4e53ae2 536 DEBUG(" L1:%d==%f L2:%d==%f\n", sIOw8.s.L1pwm100, fL1level, sIOw8.s.L2pwm255, fL2level);
prussell 23:78aad4e53ae2 537 //TODO: Update Outputs and settings (Includes flags for: Factory Reset, Enter Test Mode, Enter Demo Mode)
prussell 23:78aad4e53ae2 538
prussell 23:78aad4e53ae2 539 //} else if (tHandle == LinkLossHandle) { // TODO: Handle LinkLoss Changes
prussell 23:78aad4e53ae2 540 //x pServiceLinkLoss->setAlertLevel( AlertLevel_t newLevel )
prussell 23:78aad4e53ae2 541 //x Can be Triggered by MCP or BluetoothLEGatt sample changing Linkloss setting:
prussell 23:78aad4e53ae2 542 //x Alert=1: Debug=BLEi: Callback_BLE_onDataWritten(Handle:12, eOp:1, uOffset:0 uLen:1 Data0[0x01]=Data[])
prussell 23:78aad4e53ae2 543 //x Alert=2: Debug=BLEi: Callback_BLE_onDataWritten(Handle:12, eOp:1, uOffset:0 uLen:1 Data0[0x02]=Data[])
prussell 23:78aad4e53ae2 544 //} else if (tHandle == IOr4.getValueHandle()) { // Readonly, shouldn't occur
prussell 23:78aad4e53ae2 545 //} else if (tHandle == IOn4.getValueHandle()) { // Notifyonly, shouldn't occur
prussell 9:2d11beda333f 546 } else {
prussell 23:78aad4e53ae2 547 DEBUG("\n Unknown onWrite(tHandle:%d)\n\n", tHandle);
prussell 26:942faa4201d5 548 //This appears to happen at the beginning of a FOTA DFU Update, 20150126PR
prussell 9:2d11beda333f 549 }
prussell 0:0217a862b047 550 }
prussell 0:0217a862b047 551
prussell 15:b2c8bdef2d20 552 void Callback_BLE_onUpdatesEnabled(Gap::Handle_t tHandle) // Notifications
prussell 15:b2c8bdef2d20 553 { //Triggered when click the UpdateContinuousIcon in nRF-MCP(ThreeDownArrows)
prussell 17:93538044f003 554 if (tHandle == IOn4.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Enabled - IOn4 == Use Buttons to Trigger Update\n", tHandle); //This Occurs when selected by App nRF-MCP as has Notify property set
prussell 16:3e83f2babdfb 555 } else if (tHandle == IOr4.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Enabled - IOr4\n", tHandle); // Notify not enabled on this Characteristic
prussell 16:3e83f2babdfb 556 } else if (tHandle == IOw8.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Enabled - IOw8\n", tHandle); // Notify not enabled on this Characteristic
prussell 16:3e83f2babdfb 557 } else { DEBUG("\nBLEi: onUpdates(Handle:%d) Enabled - Characteristic?\n", tHandle);
prussell 15:b2c8bdef2d20 558 }
prussell 16:3e83f2babdfb 559 //TODO: process Enable for Each Notify Characteriistic of each Service
prussell 15:b2c8bdef2d20 560 }
prussell 15:b2c8bdef2d20 561
prussell 15:b2c8bdef2d20 562 void Callback_BLE_onUpdatesDisabled(Gap::Handle_t tHandle) // Notifications
prussell 10:ee3a359f7d3f 563 { //Triggered when click the UpdateContinuousIcon in nRF-MCP(ThreeDownArrows)
prussell 16:3e83f2babdfb 564 if (tHandle == IOn4.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Disabled - IOn4\n", tHandle); //This Occurs when selected by App nRF-MCP as has Notify property set
prussell 16:3e83f2babdfb 565 } else if (tHandle == IOr4.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Disabled - IOr4\n", tHandle); // Notify not enabled on this Characteristic
prussell 16:3e83f2babdfb 566 } else if (tHandle == IOw8.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Disabled - IOw8\n", tHandle); // Notify not enabled on this Characteristic
prussell 16:3e83f2babdfb 567 } else { DEBUG("\nBLEi: onUpdates(Handle:%d) Disabled - Characteristic?\n", tHandle);
prussell 9:2d11beda333f 568 }
prussell 16:3e83f2babdfb 569 //TODO: process Disable for Each Notify Characteriistic of each Service
prussell 0:0217a862b047 570 }
prussell 15:b2c8bdef2d20 571 void Callback_BLE_onConfirmRx(Gap::Handle_t tHandle) // Confirmations??
prussell 15:b2c8bdef2d20 572 {
prussell 15:b2c8bdef2d20 573 DEBUG("\nBLEi: ConfirmationRx(Handle:%d)\n", tHandle);
prussell 15:b2c8bdef2d20 574 }
prussell 15:b2c8bdef2d20 575
prussell 0:0217a862b047 576
prussell 5:d36bbb315e31 577 // Adopted 20141213 from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LinkLoss/file/440ee5e8595f/main.cpp
prussell 5:d36bbb315e31 578 void Callback_BLE_onLinkLoss(LinkLossService::AlertLevel_t level)
prussell 5:d36bbb315e31 579 {
prussell 10:ee3a359f7d3f 580 printf("\nBLEi: Link Loss Alert, Level:%d\n", level);
prussell 10:ee3a359f7d3f 581 //TODO: Handle Link Loss, maybe lower power mode and/or advertising mode
prussell 5:d36bbb315e31 582 }
prussell 10:ee3a359f7d3f 583 //==========BLE:HRM==========
prussell 8:f187ba55aed2 584 //Adopted 2014Dec from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_HeartRate/
prussell 8:f187ba55aed2 585 uint8_t update_hrm(void)//(bool bInit)
prussell 8:f187ba55aed2 586 {
prussell 8:f187ba55aed2 587 static uint8_t u8_hrm = 100;
prussell 10:ee3a359f7d3f 588 if (++u8_hrm >= 175) {
prussell 8:f187ba55aed2 589 u8_hrm = 100;
prussell 10:ee3a359f7d3f 590 DEBUG(" HRM>100");
prussell 10:ee3a359f7d3f 591 } else {
prussell 10:ee3a359f7d3f 592 DEBUG(" HRM:%d", u8_hrm);
prussell 10:ee3a359f7d3f 593 }
prussell 8:f187ba55aed2 594 pServiceHRM->updateHeartRate( u8_hrm );// Update Characteristic so sent by BLE
prussell 8:f187ba55aed2 595 return(u8_hrm);
prussell 8:f187ba55aed2 596 }
prussell 10:ee3a359f7d3f 597 //==========BLE:HTM(Using nRF Internal Temperature)==========
prussell 10:ee3a359f7d3f 598 // *If not using nRF51822 IC then change this to a simple counter like BLE:Battery section
prussell 10:ee3a359f7d3f 599 // Adopted 2014Dec from: https://developer.mbed.org/users/takafuminaka/code/BLE_HTM_by_InTempSensr/
prussell 8:f187ba55aed2 600 // Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml
prussell 8:f187ba55aed2 601 // HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml
prussell 9:2d11beda333f 602 //****Although nRF-MCP displays float OK, the HTM Apps don't, it is likely IEEE format required like in the original project: BLE_HTM_by_InTempSensr
prussell 8:f187ba55aed2 603 float update_htm(void)
prussell 8:f187ba55aed2 604 {
prussell 8:f187ba55aed2 605 //static float fTemperature = 0;//-123.456;
prussell 8:f187ba55aed2 606 int32_t i32_temp;
prussell 12:8bac5f5d3a3e 607 sd_temp_get(&i32_temp); //Read the nRF Internal Temperature (Die in 0.25'C steps, Offset:TBD), TODO:Check Scaling
prussell 8:f187ba55aed2 608 float fTemperature = (float(i32_temp)/4.0) - 16.0; // Scale&Shift (0.25'C from -16'C?)
prussell 8:f187ba55aed2 609
prussell 8:f187ba55aed2 610 //{//Force to IEEE format to match needs of Apps like nRF-HTM and nRF-Toolbox:HTM
prussell 8:f187ba55aed2 611 // 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 612 // uint8_t exponent = 0xFE; //exponent is -2
prussell 8:f187ba55aed2 613 // uint32_t mantissa = (uint32_t)(fTemperature*100);
prussell 8:f187ba55aed2 614 // uint32_t temp_ieee11073 = ((((uint32_t)exponent) << 24) | (mantissa)); //Note: Assumes Mantissa within 24bits
prussell 8:f187ba55aed2 615 // memcpy(((uint8_t*)&fTemperature)+1, (uint8_t*)&temp_ieee11073, 4); //Overwrite with IEEE format float
prussell 8:f187ba55aed2 616 //}
prussell 8:f187ba55aed2 617
prussell 8:f187ba55aed2 618 pServiceHTM->updateTemperature( fTemperature );// Update Characteristic so sent by BLE
prussell 10:ee3a359f7d3f 619 DEBUG(" HTM%03d==%2.2f", i32_temp, fTemperature);
prussell 8:f187ba55aed2 620 return(fTemperature);
prussell 8:f187ba55aed2 621 }
prussell 10:ee3a359f7d3f 622 //==========BLE:Battery==========
prussell 8:f187ba55aed2 623 uint8_t update_batt(void)
prussell 8:f187ba55aed2 624 {
prussell 8:f187ba55aed2 625 static uint8_t u8_BattPercent=33; //Level: 0..100%
prussell 8:f187ba55aed2 626 u8_BattPercent <= 50 ? u8_BattPercent=100 : u8_BattPercent--; // Simulate Battery Decay
prussell 8:f187ba55aed2 627 pServiceBattery->updateBatteryLevel( u8_BattPercent ); // Update Characteristic so sent by BLE
prussell 10:ee3a359f7d3f 628 DEBUG(" Batt%03d%%", u8_BattPercent);
prussell 8:f187ba55aed2 629 return(u8_BattPercent);
prussell 8:f187ba55aed2 630 }
prussell 9:2d11beda333f 631
prussell 10:ee3a359f7d3f 632 //==========Functions:Timer==========
prussell 25:1c6c2895f729 633 uint32_t u32_wakeevents=0, u32_wakelast=0; // Counter&Register for tracking Wake Events (to see monitor their Frequency)
prussell 11:7d02fe5ebea5 634 static volatile uint8_t uTicker1;//Volatile, don't optimize, changes under interrupt control
prussell 10:ee3a359f7d3f 635 void CallbackTicker1(void)
prussell 10:ee3a359f7d3f 636 {
prussell 11:7d02fe5ebea5 637 static uint32_t u32_Counter; // Counter for checking Timing
prussell 25:1c6c2895f729 638 DEBUG("\nBLEi: Ticker(%04u) WakeEvents(%d)", ++u32_Counter, u32_wakeevents);
prussell 25:1c6c2895f729 639 //if (!bAppControl) { fL1level+=0.1; if (fL1level>0.5){fL1level = 0.1;}; fL1pwm=fL1level;}//If host not controlling LED then ramp blink to show life
prussell 25:1c6c2895f729 640 { fL1level+=0.1; if (fL1level>0.5){fL1level = 0.1;}; fL1pwm=fL1level;}//Allow Ticker to regain control after a host change to LEDs
prussell 11:7d02fe5ebea5 641 uTicker1++; // Flag event, using counter so can detect missed events
prussell 10:ee3a359f7d3f 642 }
prussell 11:7d02fe5ebea5 643
prussell 0:0217a862b047 644 //==========main==========
prussell 0:0217a862b047 645 int main(void)
prussell 12:8bac5f5d3a3e 646 {
prussell 14:b968df367145 647 fL1level = 1.0; fL1pwm = fL1level;//Start LED1=OnMax
prussell 14:b968df367145 648 fL2level = 0.2; fL2pwm = fL2level;//Start LED2=Dim
prussell 6:5b6fb35b4450 649
prussell 6:5b6fb35b4450 650 //Restart TeraTerm just before Pressing Reset on mbed, 9600-8N1(No Flow Control)
prussell 6:5b6fb35b4450 651 DEBUG("\nBLE: ___%s___\n", pcDeviceName);
prussell 14:b968df367145 652
prussell 14:b968df367145 653 //ARM Predefines: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/BABJFEFG.html
prussell 14:b968df367145 654 // *Some are numbers not strings so printf(%s) not always appropriate
prussell 14:b968df367145 655 DEBUG(" ARM Compiler Predefines:\n");
prussell 14:b968df367145 656 DEBUG(" Built UTC:[ %s %s ]\n", __DATE__, __TIME__);
prussell 14:b968df367145 657 DEBUG(" __arm__[%d]", __arm__);
prussell 14:b968df367145 658 DEBUG(" __ARMCC_VERSION [%d]=[P:major V:minor bbbb:build]\n", __ARMCC_VERSION);
prussell 14:b968df367145 659 DEBUG(" __VERSION__(gnu Compiler)[" __VERSION__ "]\n");
prussell 14:b968df367145 660 //DEBUG(" __STDC_VERSION__ [%d]\n", __STDC_VERSION__);
prussell 14:b968df367145 661 //DEBUG(" __BIG_ENDIAN[%d] ", __BIG_ENDIAN);
prussell 14:b968df367145 662 DEBUG(" __OPTIMISE_LEVEL[%d]", __OPTIMISE_LEVEL);
prussell 14:b968df367145 663 //DEBUG(" __OPTIMISE_SPACE[%d]", __OPTIMISE_SPACE);
prussell 14:b968df367145 664 DEBUG(" __OPTIMISE_TIME[%d]", __OPTIMISE_TIME);
prussell 14:b968df367145 665 DEBUG("\n __MODULE__[" __MODULE__ "] __FILE__[" __FILE__ "] __BASE_FILE__[" __BASE_FILE__ "]\n");
prussell 14:b968df367145 666 DEBUG(" __FUNCTION__[%s] __PRETTY_FUNCTION__[%s]\n", __FUNCTION__, __PRETTY_FUNCTION__)
prussell 14:b968df367145 667
prussell 15:b2c8bdef2d20 668 //vShowIO(); Show Raw initialized values before any BLE
prussell 0:0217a862b047 669
prussell 0:0217a862b047 670 Ticker ticker1; //PR: Timer Object(Structure)
prussell 12:8bac5f5d3a3e 671 ticker1.attach(CallbackTicker1, 5.0); //PR: Timer Handler, Float=PeriodSeconds (Note BLE default wakes about 50Hz/20msec)
prussell 0:0217a862b047 672
prussell 3:a98203f84063 673 //BLE1: Setup BLE Service (and event actions) //TODO: Check for services declared before main() - Is that OK?
prussell 14:b968df367145 674 DEBUG("\nBLE: Connect App for Data: nRF-MCP, nRF-Toolbox:HRM/HTM, Android Sample BluetoothLeGatt, etc.\n");
prussell 14:b968df367145 675 DEBUG(" nRF-MCP: App->mbed: LinkLoss->AlertLevel(UpArrow)\n");
prussell 14:b968df367145 676 DEBUG(" nRF-MCP: App->mbed: BatteryService->BatteryLevel(DownArrow)\n");
prussell 14:b968df367145 677 DEBUG(" nRF-MCP: mbed->App: BatteryService->BatteryLevel->EnableNotify(ThreeDownArrows), Also App Acks the send=DEBUG('SentI')\n");
prussell 14:b968df367145 678
prussell 3:a98203f84063 679 DEBUG("BLE: Setup BLE\n");
prussell 0:0217a862b047 680 ble.init();
prussell 12:8bac5f5d3a3e 681 ble.onDisconnection(Callback_BLE_onDisconnect); //PR: Host disconnects, restart advertising, clear any unnecessary functions to save power
prussell 12:8bac5f5d3a3e 682 ble.onConnection(Callback_BLE_onConnect); //PR: Host connects (Not required if no actions enabled, enabled now just for debug)
prussell 12:8bac5f5d3a3e 683 ble.onDataSent(Callback_BLE_onNotifySent); //PR: Occurs when a Notify Characteristic has been updated and sent over BLE
prussell 12:8bac5f5d3a3e 684 ble.onDataWritten(Callback_BLE_onDataWritten); //PR: Occurs when an update to a Characteristic has been received over BLE
prussell 12:8bac5f5d3a3e 685 ble.onTimeout(Callback_BLE_onTimeout); //PR: ??? Hasn't occured, TODO: Monitor and find out what causes this
prussell 12:8bac5f5d3a3e 686 ble.onUpdatesEnabled(Callback_BLE_onUpdatesEnabled);//PR: Occurs when host enables notify on a Characteristic that has Notify property set
prussell 15:b2c8bdef2d20 687 ble.onUpdatesDisabled(Callback_BLE_onUpdatesDisabled); //TODO:
prussell 15:b2c8bdef2d20 688 ble.onConfirmationReceived(Callback_BLE_onConfirmRx); //TODO:
prussell 25:1c6c2895f729 689 //NotAvailableOnlineYet20150126 ble.setReadAuthorizationCallback(Callback_BLE_onDataRead);//TODO: Test new callback "setReadAuthorizationCallback()", then can read sensors live instead of polling them continuously.
prussell 8:f187ba55aed2 690
prussell 6:5b6fb35b4450 691 //BLE2: Setup Services (with their initial values and options)
prussell 3:a98203f84063 692 DEBUG("BLE: Setup Services\n");
prussell 4:976394791d7a 693 // *Order here affects order in nRF-MCP Discovery of Services
prussell 8:f187ba55aed2 694 DeviceInformationService ServiceDeviceInfo(ble, "Maker", pcDeviceName, "sn1234", "hw00", "fw00", "sw00");//(BLEDevice), pcManufacturer, pcModelNumber, pcSerialNumber, pcHWver, pcFWver, pcSWver
prussell 9:2d11beda333f 695 pServiceDeviceInfo = &ServiceDeviceInfo; //DEBUG(" Handle Service DeviceInfo:%d\n", ServiceDeviceInfo.XXXgetHandle());
prussell 8:f187ba55aed2 696 LinkLossService ServiceLinkLoss(ble, Callback_BLE_onLinkLoss, LinkLossService::HIGH_ALERT); //New20141213, TBD
prussell 8:f187ba55aed2 697 pServiceLinkLoss = &ServiceLinkLoss;
prussell 8:f187ba55aed2 698 BatteryService ServiceBattery(ble, 10);
prussell 8:f187ba55aed2 699 pServiceBattery = &ServiceBattery;
prussell 8:f187ba55aed2 700 HeartRateService ServiceHRM(ble, (uint8_t)111, HeartRateService::LOCATION_FINGER);
prussell 8:f187ba55aed2 701 pServiceHRM = &ServiceHRM;
prussell 8:f187ba55aed2 702 HealthThermometerService ServiceHTM(ble, 33.3, HealthThermometerService::LOCATION_EAR);
prussell 8:f187ba55aed2 703 pServiceHTM = &ServiceHTM;
prussell 8:f187ba55aed2 704 //UARTService ServiceUART(ble);
prussell 8:f187ba55aed2 705 // pServiceUART = &ServiceUART;
prussell 5:d36bbb315e31 706
prussell 12:8bac5f5d3a3e 707 DEBUG("BLE: Setup Custom IO Service\n");
prussell 10:ee3a359f7d3f 708 ble.addService(ServiceIO); //Pointer: pServiceIO
prussell 15:b2c8bdef2d20 709 vShowIO(); // Show Initialized values with bleIO initialized (includes tHandle)
prussell 12:8bac5f5d3a3e 710 //TODO: Ensure outputs in correct Initial state
prussell 9:2d11beda333f 711
prussell 3:a98203f84063 712 //BLE3: Setup advertising
prussell 10:ee3a359f7d3f 713 // 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 10:ee3a359f7d3f 714 // If there isn't enough space, then the accumulate payload won't add that block to the advertising, it won't add a partial block, and if name last then device shows as unnamed in App.
prussell 9:2d11beda333f 715 DEBUG("BLE: Setup Advertising - Apps like HRM/HTM/UART require matching UUID\n");
prussell 6:5b6fb35b4450 716 ble.clearAdvertisingPayload(); //Prep
prussell 6:5b6fb35b4450 717 ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); //PR: Advertise 1sec (1Hz)
prussell 6:5b6fb35b4450 718 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //PR: TODO: To Study
prussell 6:5b6fb35b4450 719 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //PR: BLE Only (Option:LE_LIMITED_DISCOVERABLE)
prussell 6:5b6fb35b4450 720 // Does "LE_GENERAL_DISCOVERABLE" affect whether UUID needs to be advertised to discover services?
prussell 10:ee3a359f7d3f 721 //a ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // Multiple UUID16 for Standard Services
prussell 11:7d02fe5ebea5 722 ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)puUUID128_IOAdvertise, sizeof(puUUID128_IOAdvertise)); //Single UUID128 for primary Service
prussell 11:7d02fe5ebea5 723
prussell 10:ee3a359f7d3f 724 //? PR: I'm not sure what these lines do, they were inherited from an example:
prussell 10:ee3a359f7d3f 725 //? ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
prussell 10:ee3a359f7d3f 726 //? ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
prussell 9:2d11beda333f 727
prussell 6:5b6fb35b4450 728 // Add LocalName last so if Advertising too long will easily see as Name won't be available for the device.
prussell 6:5b6fb35b4450 729 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)pcDeviceName, sizeof(pcDeviceName)-1);//PR: LocalName (No NULL)
prussell 6:5b6fb35b4450 730 ble.startAdvertising();
prussell 3:a98203f84063 731
prussell 10:ee3a359f7d3f 732 //Example Advertising (Max 31 bytes): 0x01020304050607080910111213141516171819202122232425262728293031
prussell 6:5b6fb35b4450 733 // Example Raw Advertising caught by App nRF-MCP: 0x020106070309180A180D180909626C655052763034
prussell 6:5b6fb35b4450 734 // = Len02 Type01 Value06 (Flags: BREDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE)
prussell 6:5b6fb35b4450 735 // = Len07 Type03 Values: 0918 0A18 0D18 (ListUUID16: 1809 180A 180D )
prussell 6:5b6fb35b4450 736 // = Len09 Type09 Values: 62 6C 65 50 52 76 30 34 (LocalName = "blePRv04")
prussell 6:5b6fb35b4450 737 // Example Raw Advertising caught by App nRF-MCP: 0x0201061106FB349B5F80000080001000000F180000070209180A180D18
prussell 6:5b6fb35b4450 738 // = Len02 Type01 Value06 (Flags: BREDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE)
prussell 6:5b6fb35b4450 739 // = Len11 Type06 ValueFB349B5F8000008000100000_0F18_0000 (UUID128: BluetoothBattery=0x180F)
prussell 6:5b6fb35b4450 740 // = Len07 Type02 Value 0918 0A18 0D18 (UUID16: 1809 180A 180D )
prussell 6:5b6fb35b4450 741 // = LocalName field wasn't appended as insufficient space, so Device won't be named when scanning.
prussell 0:0217a862b047 742
prussell 12:8bac5f5d3a3e 743 // Setup InterruptIn for Buttons (coded for nRF51822-mkit polarities on these buttons)
prussell 11:7d02fe5ebea5 744 DEBUG("BLE: Enable Button Interrupts\n");
prussell 12:8bac5f5d3a3e 745 B1int.fall(&onB1press); // Button1 Press/fall
prussell 12:8bac5f5d3a3e 746 B1int.rise(&onB1release); // Button1 Release/rise
prussell 12:8bac5f5d3a3e 747 B2int.fall(&onB2press); // Button2 Press/fall
prussell 12:8bac5f5d3a3e 748 B2int.rise(&onB2release); // Button2 Release/rise
prussell 11:7d02fe5ebea5 749
prussell 0:0217a862b047 750 DEBUG("BLE: Main Loop\n");
prussell 0:0217a862b047 751 while (true) {
prussell 11:7d02fe5ebea5 752 if (uTicker1 && ble.getGapState().connected) { //If Ticker1 and Connected then Update Appropriate Data
prussell 11:7d02fe5ebea5 753 uTicker1 = 0; // Clear flag for next Ticker1, see CallbackTicker1(), TODO: log if missed any ticks
prussell 3:a98203f84063 754
prussell 3:a98203f84063 755 // Read Sensors, and update matching Service Characteristics (only if connected)
prussell 4:976394791d7a 756 // *Order here doesn't affect order in nRF-MCP Discovery of Services
prussell 6:5b6fb35b4450 757 //TBD: Maybe save power by not Tx unless enabled by App?
prussell 8:f187ba55aed2 758 // The Services are discovered if they were setup/started (They don't need update to be discovered)
prussell 8:f187ba55aed2 759 update_htm();
prussell 8:f187ba55aed2 760 update_hrm();
prussell 8:f187ba55aed2 761 update_batt();
prussell 8:f187ba55aed2 762
prussell 10:ee3a359f7d3f 763 //a vUpdate_IOw8();
prussell 12:8bac5f5d3a3e 764 //a vUpdate_IOr4();
prussell 12:8bac5f5d3a3e 765 //a vUpdate_IOn4();
prussell 9:2d11beda333f 766
prussell 12:8bac5f5d3a3e 767 DEBUG(" BLE:Wakes:%04u,Delta:%03u ", u32_wakeevents, u32_wakeevents-u32_wakelast); //For Evaluating Timing
prussell 3:a98203f84063 768 u32_wakelast = u32_wakeevents;
prussell 11:7d02fe5ebea5 769 } else if (uTicker1) {
prussell 11:7d02fe5ebea5 770 uTicker1 = 0; // Clear flag for next Ticker1, see CallbackTicker1(), TODO: log if missed any ticks
prussell 12:8bac5f5d3a3e 771 DEBUG(" BLE: Tick while unconnected ");
prussell 12:8bac5f5d3a3e 772 } else if (bNotifySent){
prussell 12:8bac5f5d3a3e 773 bNotifySent=false; //clear flag Notify Characteristic Transmitted
prussell 12:8bac5f5d3a3e 774 DEBUG(" BLE: Notify(%u) ", uNotifyBLE);
prussell 0:0217a862b047 775 } else {
prussell 11:7d02fe5ebea5 776 //DEBUG("BLE: Wait for Event\n\r"); //x Debug output here causes endless wakes from sleep()
prussell 12:8bac5f5d3a3e 777 ble.waitForEvent(); //PR: Like sleep() with ble handling. TODO: Handle Error return
prussell 0:0217a862b047 778 u32_wakeevents++; //PR: Count events for frequency monitoring (20141207PR: nRF51822 mbed HRM = 50Hz)
prussell 25:1c6c2895f729 779 //if (!bAppControl) { fL2level+=0.25; if (fL2level>0.5){fL2level = 0.0;}; fL2pwm=fL2level;} //If host not controling LED then Ramp Blink to show life
prussell 25:1c6c2895f729 780 //{ fL2level+=0.25; if (fL2level>0.5){fL2level = 0.0;}; fL2pwm=fL2level;} //Allow Ticker to regain control after a host change to LEDs
prussell 25:1c6c2895f729 781
prussell 25:1c6c2895f729 782 //** Possibly PWM is causing extra wakes?
prussell 25:1c6c2895f729 783
prussell 12:8bac5f5d3a3e 784 }
prussell 0:0217a862b047 785 }
prussell 0:0217a862b047 786 }
prussell 10:ee3a359f7d3f 787 //========== end of main.cpp ==========
prussell 23:78aad4e53ae2 788
prussell 23:78aad4e53ae2 789