Chanel's edits
Dependencies: max32630fthr USBDevice
PPGService.h@15:b15b4b6c6da8, 2020-03-10 (annotated)
- 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?
User | Revision | Line number | New 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__*/ |