51 52 with same code
Dependencies: MtSense06
Fork of MtConnect04S_MtSense06 by
PulseOximeterService.h@1:0ec0e5694c4a, 2017-02-23 (annotated)
- Committer:
- bcc6
- Date:
- Thu Feb 23 09:31:56 2017 +0000
- Revision:
- 1:0ec0e5694c4a
- Parent:
- 0:528034040a12
Change the data endian of SpO2 & HeartRate
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bcc6 | 0:528034040a12 | 1 | /* Copyright (c) 2016 MtM Technology Corporation, MIT License |
bcc6 | 0:528034040a12 | 2 | * |
bcc6 | 0:528034040a12 | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
bcc6 | 0:528034040a12 | 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
bcc6 | 0:528034040a12 | 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
bcc6 | 0:528034040a12 | 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
bcc6 | 0:528034040a12 | 7 | * furnished to do so, subject to the following conditions: |
bcc6 | 0:528034040a12 | 8 | * |
bcc6 | 0:528034040a12 | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
bcc6 | 0:528034040a12 | 10 | * substantial portions of the Software. |
bcc6 | 0:528034040a12 | 11 | * |
bcc6 | 0:528034040a12 | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
bcc6 | 0:528034040a12 | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
bcc6 | 0:528034040a12 | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
bcc6 | 0:528034040a12 | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
bcc6 | 0:528034040a12 | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
bcc6 | 0:528034040a12 | 17 | */ |
bcc6 | 0:528034040a12 | 18 | #ifndef __BLE_PULSE_OXIMETER_SERVICE_H__ |
bcc6 | 0:528034040a12 | 19 | #define __BLE_PULSE_OXIMETER_SERVICE_H__ |
bcc6 | 0:528034040a12 | 20 | |
bcc6 | 0:528034040a12 | 21 | #include "ble/BLE.h" |
bcc6 | 0:528034040a12 | 22 | |
bcc6 | 0:528034040a12 | 23 | class PulseOximeterService { |
bcc6 | 0:528034040a12 | 24 | public: |
bcc6 | 0:528034040a12 | 25 | PulseOximeterService(BLE &_ble, float spo2, float pr) : |
bcc6 | 0:528034040a12 | 26 | ble(_ble), |
bcc6 | 0:528034040a12 | 27 | plxMeasValueBytes(spo2, pr), |
bcc6 | 0:528034040a12 | 28 | plxFeatValueBytes(), |
bcc6 | 0:528034040a12 | 29 | rawValueBytes(), |
bcc6 | 0:528034040a12 | 30 | flagSigValueBytes(), |
bcc6 | 0:528034040a12 | 31 | plxSpotCheckMeasurementCharacteristic(0x2A5E/* UUID:PLX Spot-Check Measurement */, |
bcc6 | 0:528034040a12 | 32 | plxMeasValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 33 | PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 34 | PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 35 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE, |
bcc6 | 0:528034040a12 | 36 | NULL, 0, false |
bcc6 | 0:528034040a12 | 37 | ), |
bcc6 | 0:528034040a12 | 38 | plxFeaturesCharacteristic(0x2A60/* UUID:PLX Features */, |
bcc6 | 0:528034040a12 | 39 | plxFeatValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 40 | PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 41 | PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 42 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ, |
bcc6 | 0:528034040a12 | 43 | NULL, 0, false |
bcc6 | 0:528034040a12 | 44 | ), |
bcc6 | 0:528034040a12 | 45 | rawDataCharacteristic(0x2B00/* UUID:Self defined for raw data */, |
bcc6 | 0:528034040a12 | 46 | rawValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 47 | RawDataValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 48 | RawDataValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 49 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY, |
bcc6 | 0:528034040a12 | 50 | NULL, 0, false |
bcc6 | 0:528034040a12 | 51 | ), |
bcc6 | 0:528034040a12 | 52 | signalCharacteristic(0x2B01/* UUID:Self defined for flag & signal */, |
bcc6 | 0:528034040a12 | 53 | flagSigValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 54 | FlagSignalValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 55 | FlagSignalValueBytes::SIZEOF_VALUE_BYTES, |
bcc6 | 0:528034040a12 | 56 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ, |
bcc6 | 0:528034040a12 | 57 | NULL, 0, false |
bcc6 | 0:528034040a12 | 58 | ) |
bcc6 | 0:528034040a12 | 59 | { |
bcc6 | 0:528034040a12 | 60 | GattCharacteristic *charTable[] = { |
bcc6 | 0:528034040a12 | 61 | &plxSpotCheckMeasurementCharacteristic, |
bcc6 | 0:528034040a12 | 62 | &plxFeaturesCharacteristic, |
bcc6 | 0:528034040a12 | 63 | &rawDataCharacteristic, |
bcc6 | 0:528034040a12 | 64 | &signalCharacteristic |
bcc6 | 0:528034040a12 | 65 | }; |
bcc6 | 0:528034040a12 | 66 | GattService PulseOximeterService(0x1822/* UUID:Pulse Oximeter Service */, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); |
bcc6 | 0:528034040a12 | 67 | ble.gattServer().addService(PulseOximeterService); |
bcc6 | 0:528034040a12 | 68 | } |
bcc6 | 0:528034040a12 | 69 | |
bcc6 | 0:528034040a12 | 70 | void updatePlxMeas(float spo2, float pr) { |
bcc6 | 0:528034040a12 | 71 | plxMeasValueBytes.updatePlxSpotCheckMeasurement(spo2, pr); |
bcc6 | 0:528034040a12 | 72 | ble.gattServer().write(plxSpotCheckMeasurementCharacteristic.getValueHandle(), |
bcc6 | 0:528034040a12 | 73 | plxMeasValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 74 | PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES |
bcc6 | 0:528034040a12 | 75 | ); |
bcc6 | 0:528034040a12 | 76 | } |
bcc6 | 0:528034040a12 | 77 | |
bcc6 | 0:528034040a12 | 78 | void updateRaw(uint8_t *raw) { |
bcc6 | 0:528034040a12 | 79 | rawValueBytes.updateRawData(raw); |
bcc6 | 0:528034040a12 | 80 | ble.gattServer().write(rawDataCharacteristic.getValueHandle(), |
bcc6 | 0:528034040a12 | 81 | rawValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 82 | RawDataValueBytes::SIZEOF_VALUE_BYTES |
bcc6 | 0:528034040a12 | 83 | ); |
bcc6 | 0:528034040a12 | 84 | } |
bcc6 | 0:528034040a12 | 85 | |
bcc6 | 0:528034040a12 | 86 | void updateStatusFlagAndSignalQuality(uint8_t statusFlag, uint8_t signalQuality) { |
bcc6 | 0:528034040a12 | 87 | flagSigValueBytes.updateFlagSignal(statusFlag, signalQuality); |
bcc6 | 0:528034040a12 | 88 | ble.gattServer().write(signalCharacteristic.getValueHandle(), |
bcc6 | 0:528034040a12 | 89 | flagSigValueBytes.getPointer(), |
bcc6 | 0:528034040a12 | 90 | FlagSignalValueBytes::SIZEOF_VALUE_BYTES |
bcc6 | 0:528034040a12 | 91 | ); |
bcc6 | 0:528034040a12 | 92 | } |
bcc6 | 0:528034040a12 | 93 | //================================================================================== |
bcc6 | 0:528034040a12 | 94 | private: |
bcc6 | 0:528034040a12 | 95 | struct PlxSpotCheckMeasurementValueBytes { |
bcc6 | 0:528034040a12 | 96 | static const unsigned OFFSET_OF_FLAGS = 0; |
bcc6 | 0:528034040a12 | 97 | static const unsigned OFFSET_OF_SPO2 = 1; |
bcc6 | 0:528034040a12 | 98 | static const unsigned OFFSET_OF_PR = 3; |
bcc6 | 0:528034040a12 | 99 | static const unsigned SIZEOF_VALUE_BYTES = 5; |
bcc6 | 0:528034040a12 | 100 | |
bcc6 | 0:528034040a12 | 101 | PlxSpotCheckMeasurementValueBytes(float spo2, float pr) : bytes() { |
bcc6 | 0:528034040a12 | 102 | bytes[OFFSET_OF_FLAGS] = 0x00; /* All fields aren't present */ |
bcc6 | 0:528034040a12 | 103 | updatePlxSpotCheckMeasurement(spo2, pr); |
bcc6 | 0:528034040a12 | 104 | } |
bcc6 | 0:528034040a12 | 105 | |
bcc6 | 0:528034040a12 | 106 | void updatePlxSpotCheckMeasurement(float spo2, float pr) { |
bcc6 | 0:528034040a12 | 107 | uint16_t sfloat_spo2 = ieee11073_SFLOAT(spo2); |
bcc6 | 0:528034040a12 | 108 | uint16_t sfloat_pr = ieee11073_SFLOAT(pr); |
bcc6 | 1:0ec0e5694c4a | 109 | #if 0 |
bcc6 | 0:528034040a12 | 110 | memcpy(&bytes[OFFSET_OF_SPO2], &sfloat_spo2, sizeof(uint16_t)); |
bcc6 | 0:528034040a12 | 111 | memcpy(&bytes[OFFSET_OF_PR], &sfloat_pr, sizeof(uint16_t)); |
bcc6 | 1:0ec0e5694c4a | 112 | #else |
bcc6 | 1:0ec0e5694c4a | 113 | bytes[OFFSET_OF_SPO2+0] = (uint8_t)(sfloat_spo2 >> 8); |
bcc6 | 1:0ec0e5694c4a | 114 | bytes[OFFSET_OF_SPO2+1] = (uint8_t)(sfloat_spo2 >> 0); |
bcc6 | 1:0ec0e5694c4a | 115 | bytes[OFFSET_OF_PR+0] = (uint8_t)(sfloat_pr >> 8); |
bcc6 | 1:0ec0e5694c4a | 116 | bytes[OFFSET_OF_PR+1] = (uint8_t)(sfloat_pr >> 0); |
bcc6 | 1:0ec0e5694c4a | 117 | #endif |
bcc6 | 0:528034040a12 | 118 | } |
bcc6 | 0:528034040a12 | 119 | |
bcc6 | 0:528034040a12 | 120 | uint8_t *getPointer(void) { return bytes; } |
bcc6 | 0:528034040a12 | 121 | const uint8_t *getPointer(void) const { return bytes; } |
bcc6 | 0:528034040a12 | 122 | |
bcc6 | 0:528034040a12 | 123 | uint16_t ieee11073_SFLOAT(float v) { |
bcc6 | 0:528034040a12 | 124 | /* Bitmap: eeee_mmmm_mmmm_mmmm */ |
bcc6 | 0:528034040a12 | 125 | /* Exponent: 4bits, Base10, 2'sComplement */ |
bcc6 | 0:528034040a12 | 126 | /* Mantissa: 12bits, 2's Complement */ |
bcc6 | 0:528034040a12 | 127 | uint8_t exponent = 0; |
bcc6 | 0:528034040a12 | 128 | uint16_t mantissa = (uint16_t)v; |
bcc6 | 0:528034040a12 | 129 | return (((uint16_t)exponent) << 12) | mantissa; |
bcc6 | 0:528034040a12 | 130 | } |
bcc6 | 0:528034040a12 | 131 | |
bcc6 | 0:528034040a12 | 132 | uint8_t bytes[SIZEOF_VALUE_BYTES]; |
bcc6 | 0:528034040a12 | 133 | }; |
bcc6 | 0:528034040a12 | 134 | //------------------------------------------------------------------------------- |
bcc6 | 0:528034040a12 | 135 | struct PlxFeaturesValueBytes { |
bcc6 | 0:528034040a12 | 136 | static const unsigned OFFSET_OF_SUPPORTED_FEATURES = 0; |
bcc6 | 0:528034040a12 | 137 | static const unsigned SIZEOF_VALUE_BYTES = 2; |
bcc6 | 0:528034040a12 | 138 | |
bcc6 | 0:528034040a12 | 139 | PlxFeaturesValueBytes() : bytes() { |
bcc6 | 0:528034040a12 | 140 | memset(bytes, 0x00, SIZEOF_VALUE_BYTES); /* All features aren't support */ |
bcc6 | 0:528034040a12 | 141 | } |
bcc6 | 0:528034040a12 | 142 | |
bcc6 | 0:528034040a12 | 143 | void updatePlxFeatures(uint16_t feat) { |
bcc6 | 0:528034040a12 | 144 | memcpy(&bytes[OFFSET_OF_SUPPORTED_FEATURES], &feat, SIZEOF_VALUE_BYTES); |
bcc6 | 0:528034040a12 | 145 | } |
bcc6 | 0:528034040a12 | 146 | |
bcc6 | 0:528034040a12 | 147 | uint8_t *getPointer(void) { return bytes; } |
bcc6 | 0:528034040a12 | 148 | const uint8_t *getPointer(void) const { return bytes; } |
bcc6 | 0:528034040a12 | 149 | |
bcc6 | 0:528034040a12 | 150 | uint8_t bytes[SIZEOF_VALUE_BYTES]; |
bcc6 | 0:528034040a12 | 151 | }; |
bcc6 | 0:528034040a12 | 152 | //------------------------------------------------------------------------------- |
bcc6 | 0:528034040a12 | 153 | struct RawDataValueBytes { |
bcc6 | 0:528034040a12 | 154 | static const unsigned OFFSET_OF_RAW = 0; |
bcc6 | 0:528034040a12 | 155 | static const unsigned SIZEOF_VALUE_BYTES = 18; |
bcc6 | 0:528034040a12 | 156 | |
bcc6 | 0:528034040a12 | 157 | RawDataValueBytes() : bytes() { |
bcc6 | 0:528034040a12 | 158 | memset(bytes, 0x00, SIZEOF_VALUE_BYTES); |
bcc6 | 0:528034040a12 | 159 | } |
bcc6 | 0:528034040a12 | 160 | |
bcc6 | 0:528034040a12 | 161 | void updateRawData(uint8_t *raw) { |
bcc6 | 0:528034040a12 | 162 | memcpy(&bytes[OFFSET_OF_RAW], raw, SIZEOF_VALUE_BYTES); |
bcc6 | 0:528034040a12 | 163 | } |
bcc6 | 0:528034040a12 | 164 | |
bcc6 | 0:528034040a12 | 165 | uint8_t *getPointer(void) { return bytes; } |
bcc6 | 0:528034040a12 | 166 | const uint8_t *getPointer(void) const { return bytes; } |
bcc6 | 0:528034040a12 | 167 | |
bcc6 | 0:528034040a12 | 168 | uint8_t bytes[SIZEOF_VALUE_BYTES]; |
bcc6 | 0:528034040a12 | 169 | }; |
bcc6 | 0:528034040a12 | 170 | //------------------------------------------------------------------------------- |
bcc6 | 0:528034040a12 | 171 | struct FlagSignalValueBytes { |
bcc6 | 0:528034040a12 | 172 | static const unsigned OFFSET_OF_FLAG = 0; |
bcc6 | 0:528034040a12 | 173 | static const unsigned OFFSET_OF_SIGNAL_QUALITY = 1; |
bcc6 | 0:528034040a12 | 174 | static const unsigned SIZEOF_VALUE_BYTES = 2; |
bcc6 | 0:528034040a12 | 175 | |
bcc6 | 0:528034040a12 | 176 | FlagSignalValueBytes() : bytes() { |
bcc6 | 0:528034040a12 | 177 | memset(bytes, 0x00, SIZEOF_VALUE_BYTES); |
bcc6 | 0:528034040a12 | 178 | } |
bcc6 | 0:528034040a12 | 179 | |
bcc6 | 0:528034040a12 | 180 | void updateFlagSignal(uint8_t statusFlag, uint8_t signalQuality) { |
bcc6 | 0:528034040a12 | 181 | bytes[OFFSET_OF_FLAG] = statusFlag; |
bcc6 | 0:528034040a12 | 182 | bytes[OFFSET_OF_SIGNAL_QUALITY] = signalQuality; |
bcc6 | 0:528034040a12 | 183 | } |
bcc6 | 0:528034040a12 | 184 | |
bcc6 | 0:528034040a12 | 185 | uint8_t *getPointer(void) { return bytes; } |
bcc6 | 0:528034040a12 | 186 | const uint8_t *getPointer(void) const { return bytes; } |
bcc6 | 0:528034040a12 | 187 | |
bcc6 | 0:528034040a12 | 188 | uint8_t bytes[SIZEOF_VALUE_BYTES]; |
bcc6 | 0:528034040a12 | 189 | }; |
bcc6 | 0:528034040a12 | 190 | //================================================================================== |
bcc6 | 0:528034040a12 | 191 | protected: |
bcc6 | 0:528034040a12 | 192 | BLE &ble; |
bcc6 | 0:528034040a12 | 193 | |
bcc6 | 0:528034040a12 | 194 | PlxSpotCheckMeasurementValueBytes plxMeasValueBytes; |
bcc6 | 0:528034040a12 | 195 | PlxFeaturesValueBytes plxFeatValueBytes; |
bcc6 | 0:528034040a12 | 196 | RawDataValueBytes rawValueBytes; |
bcc6 | 0:528034040a12 | 197 | FlagSignalValueBytes flagSigValueBytes; |
bcc6 | 0:528034040a12 | 198 | |
bcc6 | 0:528034040a12 | 199 | GattCharacteristic plxSpotCheckMeasurementCharacteristic; |
bcc6 | 0:528034040a12 | 200 | GattCharacteristic plxFeaturesCharacteristic; |
bcc6 | 0:528034040a12 | 201 | GattCharacteristic rawDataCharacteristic; |
bcc6 | 0:528034040a12 | 202 | GattCharacteristic signalCharacteristic; |
bcc6 | 0:528034040a12 | 203 | }; |
bcc6 | 0:528034040a12 | 204 | |
bcc6 | 0:528034040a12 | 205 | #endif /* #ifndef __BLE_PULSE_OXIMETER_SERVICE_H__*/ |