Chanel's edits

Dependencies:   max32630fthr USBDevice

Committer:
saleiferis
Date:
Tue Mar 10 20:33:49 2020 +0000
Revision:
15:b15b4b6c6da8
Parent:
14:ee2175578993
preprocessing, BLE, and serial, before pan-tompkins

Who changed what in which revision?

UserRevisionLine numberNew contents of line
saleiferis 14:ee2175578993 1 /* mbed Microcontroller Library
saleiferis 14:ee2175578993 2 * Copyright (c) 2006-2013 ARM Limited
saleiferis 14:ee2175578993 3 *
saleiferis 14:ee2175578993 4 * Licensed under the Apache License, Version 2.0 (the "License");
saleiferis 14:ee2175578993 5 * you may not use this file except in compliance with the License.
saleiferis 14:ee2175578993 6 * You may obtain a copy of the License at
saleiferis 14:ee2175578993 7 *
saleiferis 14:ee2175578993 8 * http://www.apache.org/licenses/LICENSE-2.0
saleiferis 14:ee2175578993 9 *
saleiferis 14:ee2175578993 10 * Unless required by applicable law or agreed to in writing, software
saleiferis 14:ee2175578993 11 * distributed under the License is distributed on an "AS IS" BASIS,
saleiferis 14:ee2175578993 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
saleiferis 14:ee2175578993 13 * See the License for the specific language governing permissions and
saleiferis 14:ee2175578993 14 * limitations under the License.
saleiferis 14:ee2175578993 15 */
saleiferis 14:ee2175578993 16
saleiferis 14:ee2175578993 17 #ifndef MBED_BLE_PPG_SERVICE_H__
saleiferis 14:ee2175578993 18 #define MBED_BLE_PPG_SERVICE_H__
saleiferis 14:ee2175578993 19
saleiferis 14:ee2175578993 20 #include "ble/BLE.h"
saleiferis 14:ee2175578993 21
saleiferis 14:ee2175578993 22 //#if BLE_FEATURE_GATT_SERVER
saleiferis 14:ee2175578993 23
saleiferis 14:ee2175578993 24 /**
saleiferis 14:ee2175578993 25 * BLE Heart Rate Service.
saleiferis 14:ee2175578993 26 *
saleiferis 14:ee2175578993 27 * @par purpose
saleiferis 14:ee2175578993 28 *
saleiferis 14:ee2175578993 29 * Fitness applications use the heart rate service to expose the heart
saleiferis 14:ee2175578993 30 * beat per minute measured by a heart rate sensor.
saleiferis 14:ee2175578993 31 *
saleiferis 14:ee2175578993 32 * Clients can read the intended location of the sensor and the last heart rate
saleiferis 14:ee2175578993 33 * value measured. Additionally, clients can subscribe to server initiated
saleiferis 14:ee2175578993 34 * updates of the heart rate value measured by the sensor. The service delivers
saleiferis 14:ee2175578993 35 * these updates to the subscribed client in a notification packet.
saleiferis 14:ee2175578993 36 *
saleiferis 14:ee2175578993 37 * The subscription mechanism is useful to save power; it avoids unecessary data
saleiferis 14:ee2175578993 38 * traffic between the client and the server, which may be induced by polling the
saleiferis 14:ee2175578993 39 * value of the heart rate measurement characteristic.
saleiferis 14:ee2175578993 40 *
saleiferis 14:ee2175578993 41 * @par usage
saleiferis 14:ee2175578993 42 *
saleiferis 14:ee2175578993 43 * When this class is instantiated, it adds a heart rate service in the GattServer.
saleiferis 14:ee2175578993 44 * The service contains the location of the sensor and the initial value measured
saleiferis 14:ee2175578993 45 * by the sensor.
saleiferis 14:ee2175578993 46 *
saleiferis 14:ee2175578993 47 * Application code can invoke updateHeartRate() when a new heart rate measurement
saleiferis 14:ee2175578993 48 * is acquired; this function updates the value of the heart rate measurement
saleiferis 14:ee2175578993 49 * characteristic and notifies the new value to subscribed clients.
saleiferis 14:ee2175578993 50 *
saleiferis 14:ee2175578993 51 * @note You can find specification of the heart rate service here:
saleiferis 14:ee2175578993 52 * https://www.bluetooth.com/specifications/gatt
saleiferis 14:ee2175578993 53 *
saleiferis 14:ee2175578993 54 * @attention The service does not expose information related to the sensor
saleiferis 14:ee2175578993 55 * contact, the accumulated energy expanded or the interbeat intervals.
saleiferis 14:ee2175578993 56 *
saleiferis 14:ee2175578993 57 * @attention The heart rate profile limits the number of instantiations of the
saleiferis 14:ee2175578993 58 * heart rate services to one.
saleiferis 14:ee2175578993 59 */
saleiferis 14:ee2175578993 60 extern Serial pc;
saleiferis 15:b15b4b6c6da8 61 const char* UUID_STR_PPG_SERVICE = "E14C6C9D-3497-4835-8F8B-28D7AF2E6A15";
saleiferis 15:b15b4b6c6da8 62 const char* UUID_STR_PPG_RED_CHAR = "E14C6C9D-3497-4836-8F8B-28D7AF2E6A15";
saleiferis 15:b15b4b6c6da8 63 const char* UUID_STR_PPG_IR_CHAR = "E14C6C9D-3497-4837-8F8B-28D7AF2E6A15";
saleiferis 15:b15b4b6c6da8 64
saleiferis 14:ee2175578993 65
saleiferis 14:ee2175578993 66 class PPGService {
saleiferis 14:ee2175578993 67
saleiferis 14:ee2175578993 68 public:
saleiferis 14:ee2175578993 69 /**
saleiferis 14:ee2175578993 70 * Construct and initialize a heart rate service.
saleiferis 14:ee2175578993 71 *
saleiferis 14:ee2175578993 72 * The construction process adds a GATT heart rate service in @p _ble
saleiferis 14:ee2175578993 73 * GattServer, sets the value of the heart rate measurement characteristic
saleiferis 14:ee2175578993 74 * to @p ppgVal and the value of the body sensor location characteristic
saleiferis 14:ee2175578993 75 * to @p location.
saleiferis 14:ee2175578993 76 *
saleiferis 14:ee2175578993 77 * @param[in] _ble BLE device that hosts the heart rate service.
saleiferis 14:ee2175578993 78 * @param[in] ppgVal Heart beats per minute measured by the heart rate
saleiferis 14:ee2175578993 79 * sensor.
saleiferis 14:ee2175578993 80 * @param[in] location Intended location of the heart rate sensor.
saleiferis 14:ee2175578993 81 */
saleiferis 15:b15b4b6c6da8 82 PPGService(BLE &_ble, int16_t ppgValRed, int16_t ppgValIR) :
saleiferis 14:ee2175578993 83 ble(_ble),
saleiferis 15:b15b4b6c6da8 84 valueBytesRed(ppgValRed),
saleiferis 15:b15b4b6c6da8 85 valueBytesIR(ppgValIR),
saleiferis 15:b15b4b6c6da8 86 ppgValueRed(
saleiferis 15:b15b4b6c6da8 87 UUID_STR_PPG_RED_CHAR, //TODO: replace with UUID for PPG sample characteristic
saleiferis 15:b15b4b6c6da8 88 valueBytesRed.getPointer(),
saleiferis 15:b15b4b6c6da8 89 valueBytesRed.getNumValueBytes(),
saleiferis 15:b15b4b6c6da8 90 PPGValueBytes::MAX_VALUE_BYTES,
saleiferis 15:b15b4b6c6da8 91 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
saleiferis 15:b15b4b6c6da8 92 ppgValueIR(
saleiferis 15:b15b4b6c6da8 93 UUID_STR_PPG_IR_CHAR, //TODO: replace with UUID for PPG sample characteristic
saleiferis 15:b15b4b6c6da8 94 valueBytesIR.getPointer(),
saleiferis 15:b15b4b6c6da8 95 valueBytesIR.getNumValueBytes(),
saleiferis 15:b15b4b6c6da8 96 PPGValueBytes::MAX_VALUE_BYTES,
saleiferis 15:b15b4b6c6da8 97 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
saleiferis 14:ee2175578993 98 {
saleiferis 14:ee2175578993 99 //pc.printf("Setup service");
saleiferis 14:ee2175578993 100 setupService();
saleiferis 14:ee2175578993 101 }
saleiferis 14:ee2175578993 102
saleiferis 14:ee2175578993 103 /**
saleiferis 14:ee2175578993 104 * Update the heart rate that the service exposes.
saleiferis 14:ee2175578993 105 *
saleiferis 14:ee2175578993 106 * The server sends a notification of the new value to clients that have
saleiferis 14:ee2175578993 107 * subscribed to updates of the heart rate measurement characteristic; clients
saleiferis 14:ee2175578993 108 * reading the heart rate measurement characteristic after the update obtain
saleiferis 14:ee2175578993 109 * the updated value.
saleiferis 14:ee2175578993 110 *
saleiferis 14:ee2175578993 111 * @param[in] ppgVal Heart rate measured in BPM.
saleiferis 14:ee2175578993 112 *
saleiferis 14:ee2175578993 113 * @attention This function must be called in the execution context of the
saleiferis 14:ee2175578993 114 * BLE stack.
saleiferis 14:ee2175578993 115 */
saleiferis 15:b15b4b6c6da8 116 void updatePPGRedValue(uint16_t ppgVal) {
saleiferis 15:b15b4b6c6da8 117 valueBytesRed.updatePPGValue(ppgVal);
saleiferis 14:ee2175578993 118 ble.gattServer().write(
saleiferis 15:b15b4b6c6da8 119 ppgValueRed.getValueHandle(),
saleiferis 15:b15b4b6c6da8 120 valueBytesRed.getPointer(),
saleiferis 15:b15b4b6c6da8 121 valueBytesRed.getNumValueBytes()
saleiferis 15:b15b4b6c6da8 122 );
saleiferis 15:b15b4b6c6da8 123 }
saleiferis 15:b15b4b6c6da8 124 void updatePPGIRValue(uint16_t ppgVal) {
saleiferis 15:b15b4b6c6da8 125 valueBytesIR.updatePPGValue(ppgVal);
saleiferis 15:b15b4b6c6da8 126 ble.gattServer().write(
saleiferis 15:b15b4b6c6da8 127 ppgValueIR.getValueHandle(),
saleiferis 15:b15b4b6c6da8 128 valueBytesIR.getPointer(),
saleiferis 15:b15b4b6c6da8 129 valueBytesIR.getNumValueBytes()
saleiferis 14:ee2175578993 130 );
saleiferis 14:ee2175578993 131 }
saleiferis 14:ee2175578993 132
saleiferis 14:ee2175578993 133 protected:
saleiferis 14:ee2175578993 134 /**
saleiferis 14:ee2175578993 135 * Construct and add to the GattServer the heart rate service.
saleiferis 14:ee2175578993 136 */
saleiferis 14:ee2175578993 137 void setupService(void) {
saleiferis 14:ee2175578993 138 GattCharacteristic *charTable[] = {
saleiferis 15:b15b4b6c6da8 139 &ppgValueRed,
saleiferis 15:b15b4b6c6da8 140 &ppgValueIR
saleiferis 14:ee2175578993 141 };
saleiferis 15:b15b4b6c6da8 142 GattService ppgService(
saleiferis 15:b15b4b6c6da8 143 UUID_STR_PPG_SERVICE, //TODO: ECG service UUID
saleiferis 14:ee2175578993 144 charTable,
saleiferis 14:ee2175578993 145 sizeof(charTable) / sizeof(GattCharacteristic*)
saleiferis 14:ee2175578993 146 );
saleiferis 14:ee2175578993 147
saleiferis 15:b15b4b6c6da8 148 ble.gattServer().addService(ppgService);
saleiferis 14:ee2175578993 149 }
saleiferis 14:ee2175578993 150
saleiferis 14:ee2175578993 151 protected:
saleiferis 14:ee2175578993 152 /*
saleiferis 14:ee2175578993 153 * Heart rate measurement value.
saleiferis 14:ee2175578993 154 */
saleiferis 15:b15b4b6c6da8 155 struct PPGValueBytes {
saleiferis 14:ee2175578993 156 /* 1 byte for the Flags, and up to two bytes for heart rate value. */
saleiferis 14:ee2175578993 157 static const unsigned MAX_VALUE_BYTES = 2; // int16 per ECG sample
saleiferis 14:ee2175578993 158 static const unsigned FLAGS_BYTE_INDEX = 0;
saleiferis 14:ee2175578993 159
saleiferis 14:ee2175578993 160 static const unsigned VALUE_FORMAT_BITNUM = 0;
saleiferis 14:ee2175578993 161 static const uint8_t VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM);
saleiferis 14:ee2175578993 162
saleiferis 15:b15b4b6c6da8 163 PPGValueBytes(int16_t ppgVal) : valueBytes()
saleiferis 14:ee2175578993 164 {
saleiferis 14:ee2175578993 165 updatePPGValue(ppgVal);
saleiferis 14:ee2175578993 166 }
saleiferis 14:ee2175578993 167
saleiferis 14:ee2175578993 168 void updatePPGValue(int16_t ppgVal)
saleiferis 14:ee2175578993 169 {
saleiferis 14:ee2175578993 170 *valueBytes = ppgVal;
saleiferis 14:ee2175578993 171
saleiferis 14:ee2175578993 172 }
saleiferis 14:ee2175578993 173
saleiferis 14:ee2175578993 174 uint8_t *getPointer(void)
saleiferis 14:ee2175578993 175 {
saleiferis 14:ee2175578993 176 return valueBytes;
saleiferis 14:ee2175578993 177 }
saleiferis 14:ee2175578993 178
saleiferis 14:ee2175578993 179 const uint8_t *getPointer(void) const
saleiferis 14:ee2175578993 180 {
saleiferis 14:ee2175578993 181 return valueBytes;
saleiferis 14:ee2175578993 182 }
saleiferis 14:ee2175578993 183
saleiferis 14:ee2175578993 184 unsigned getNumValueBytes(void) const
saleiferis 14:ee2175578993 185 {
saleiferis 14:ee2175578993 186 /*
saleiferis 14:ee2175578993 187 if (valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) {
saleiferis 14:ee2175578993 188 return 1 + sizeof(uint16_t);
saleiferis 14:ee2175578993 189 } else {
saleiferis 14:ee2175578993 190 return 1 + sizeof(uint8_t);
saleiferis 14:ee2175578993 191 }
saleiferis 14:ee2175578993 192 */
saleiferis 14:ee2175578993 193 return sizeof(int16_t); // sending two bytes per ECG sample
saleiferis 14:ee2175578993 194 }
saleiferis 14:ee2175578993 195
saleiferis 14:ee2175578993 196 private:
saleiferis 14:ee2175578993 197 uint8_t valueBytes[MAX_VALUE_BYTES];
saleiferis 14:ee2175578993 198 };
saleiferis 14:ee2175578993 199
saleiferis 14:ee2175578993 200 protected:
saleiferis 14:ee2175578993 201 BLE &ble;
saleiferis 15:b15b4b6c6da8 202 PPGValueBytes valueBytesRed;
saleiferis 15:b15b4b6c6da8 203 PPGValueBytes valueBytesIR;
saleiferis 15:b15b4b6c6da8 204 GattCharacteristic ppgValueRed;
saleiferis 15:b15b4b6c6da8 205 GattCharacteristic ppgValueIR;
saleiferis 14:ee2175578993 206 };
saleiferis 14:ee2175578993 207
saleiferis 14:ee2175578993 208 //#endif // BLE_FEATURE_GATT_SERVER
saleiferis 14:ee2175578993 209
saleiferis 14:ee2175578993 210 #endif /* #ifndef MBED_BLE_HEART_RATE_SERVICE_H__*/