Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MtSense06
Fork of MtConnect04S_MtSense06 by
Revision 3:cab2817f6c40, committed 2018-04-27
- Comitter:
- johnathanlyu
- Date:
- Fri Apr 27 09:59:38 2018 +0000
- Parent:
- 2:7a08b9410b96
- Commit message:
- update library flow
Changed in this revision
--- a/MtSense06.lib Fri Mar 31 08:05:22 2017 +0000 +++ b/MtSense06.lib Fri Apr 27 09:59:38 2018 +0000 @@ -1,1 +1,1 @@ -https://developer.mbed.org/teams/MtM/code/MtSense06/#2dc8b6117c1d +https://os.mbed.com/teams/MtM/code/MtSense06/#2dc8b6117c1d
--- a/PulseOximeterService.h Fri Mar 31 08:05:22 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/* Copyright (c) 2016 MtM Technology Corporation, MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef __BLE_PULSE_OXIMETER_SERVICE_H__
-#define __BLE_PULSE_OXIMETER_SERVICE_H__
-
-#include "ble/BLE.h"
-
-class PulseOximeterService {
-public:
- PulseOximeterService(BLE &_ble, float spo2, float pr) :
- ble(_ble),
- plxMeasValueBytes(spo2, pr),
- plxFeatValueBytes(),
- rawValueBytes(),
- flagSigValueBytes(),
- plxSpotCheckMeasurementCharacteristic(0x2A5E/* UUID:PLX Spot-Check Measurement */,
- plxMeasValueBytes.getPointer(),
- PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES,
- PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES,
- GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE,
- NULL, 0, false
- ),
- plxFeaturesCharacteristic(0x2A60/* UUID:PLX Features */,
- plxFeatValueBytes.getPointer(),
- PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES,
- PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES,
- GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
- NULL, 0, false
- ),
- rawDataCharacteristic(0x2B00/* UUID:Self defined for raw data */,
- rawValueBytes.getPointer(),
- RawDataValueBytes::SIZEOF_VALUE_BYTES,
- RawDataValueBytes::SIZEOF_VALUE_BYTES,
- GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY,
- NULL, 0, false
- ),
- signalCharacteristic(0x2B01/* UUID:Self defined for flag & signal */,
- flagSigValueBytes.getPointer(),
- FlagSignalValueBytes::SIZEOF_VALUE_BYTES,
- FlagSignalValueBytes::SIZEOF_VALUE_BYTES,
- GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
- NULL, 0, false
- )
- {
- GattCharacteristic *charTable[] = {
- &plxSpotCheckMeasurementCharacteristic,
- &plxFeaturesCharacteristic,
- &rawDataCharacteristic,
- &signalCharacteristic
- };
- GattService PulseOximeterService(0x1822/* UUID:Pulse Oximeter Service */, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
- ble.gattServer().addService(PulseOximeterService);
- }
-
- void updatePlxMeas(float spo2, float pr) {
- plxMeasValueBytes.updatePlxSpotCheckMeasurement(spo2, pr);
- ble.gattServer().write(plxSpotCheckMeasurementCharacteristic.getValueHandle(),
- plxMeasValueBytes.getPointer(),
- PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES
- );
- }
-
- void updateRaw(uint8_t *raw) {
- rawValueBytes.updateRawData(raw);
- ble.gattServer().write(rawDataCharacteristic.getValueHandle(),
- rawValueBytes.getPointer(),
- RawDataValueBytes::SIZEOF_VALUE_BYTES
- );
- }
-
- void updateStatusFlagAndSignalQuality(uint8_t statusFlag, uint8_t signalQuality) {
- flagSigValueBytes.updateFlagSignal(statusFlag, signalQuality);
- ble.gattServer().write(signalCharacteristic.getValueHandle(),
- flagSigValueBytes.getPointer(),
- FlagSignalValueBytes::SIZEOF_VALUE_BYTES
- );
- }
-//==================================================================================
-private:
- struct PlxSpotCheckMeasurementValueBytes {
- static const unsigned OFFSET_OF_FLAGS = 0;
- static const unsigned OFFSET_OF_SPO2 = 1;
- static const unsigned OFFSET_OF_PR = 3;
- static const unsigned SIZEOF_VALUE_BYTES = 5;
-
- PlxSpotCheckMeasurementValueBytes(float spo2, float pr) : bytes() {
- bytes[OFFSET_OF_FLAGS] = 0x00; /* All fields aren't present */
- updatePlxSpotCheckMeasurement(spo2, pr);
- }
-
- void updatePlxSpotCheckMeasurement(float spo2, float pr) {
- uint16_t sfloat_spo2 = ieee11073_SFLOAT(spo2);
- uint16_t sfloat_pr = ieee11073_SFLOAT(pr);
-#if 0
- memcpy(&bytes[OFFSET_OF_SPO2], &sfloat_spo2, sizeof(uint16_t));
- memcpy(&bytes[OFFSET_OF_PR], &sfloat_pr, sizeof(uint16_t));
-#else
- bytes[OFFSET_OF_SPO2+0] = (uint8_t)(sfloat_spo2 >> 8);
- bytes[OFFSET_OF_SPO2+1] = (uint8_t)(sfloat_spo2 >> 0);
- bytes[OFFSET_OF_PR+0] = (uint8_t)(sfloat_pr >> 8);
- bytes[OFFSET_OF_PR+1] = (uint8_t)(sfloat_pr >> 0);
-#endif
- }
-
- uint8_t *getPointer(void) { return bytes; }
- const uint8_t *getPointer(void) const { return bytes; }
-
- uint16_t ieee11073_SFLOAT(float v) {
- /* Bitmap: eeee_mmmm_mmmm_mmmm */
- /* Exponent: 4bits, Base10, 2'sComplement */
- /* Mantissa: 12bits, 2's Complement */
- uint8_t exponent = 0;
- uint16_t mantissa = (uint16_t)v;
- return (((uint16_t)exponent) << 12) | mantissa;
- }
-
- uint8_t bytes[SIZEOF_VALUE_BYTES];
- };
- //-------------------------------------------------------------------------------
- struct PlxFeaturesValueBytes {
- static const unsigned OFFSET_OF_SUPPORTED_FEATURES = 0;
- static const unsigned SIZEOF_VALUE_BYTES = 2;
-
- PlxFeaturesValueBytes() : bytes() {
- memset(bytes, 0x00, SIZEOF_VALUE_BYTES); /* All features aren't support */
- }
-
- void updatePlxFeatures(uint16_t feat) {
- memcpy(&bytes[OFFSET_OF_SUPPORTED_FEATURES], &feat, SIZEOF_VALUE_BYTES);
- }
-
- uint8_t *getPointer(void) { return bytes; }
- const uint8_t *getPointer(void) const { return bytes; }
-
- uint8_t bytes[SIZEOF_VALUE_BYTES];
- };
- //-------------------------------------------------------------------------------
- struct RawDataValueBytes {
- static const unsigned OFFSET_OF_RAW = 0;
- static const unsigned SIZEOF_VALUE_BYTES = 18;
-
- RawDataValueBytes() : bytes() {
- memset(bytes, 0x00, SIZEOF_VALUE_BYTES);
- }
-
- void updateRawData(uint8_t *raw) {
- memcpy(&bytes[OFFSET_OF_RAW], raw, SIZEOF_VALUE_BYTES);
- }
-
- uint8_t *getPointer(void) { return bytes; }
- const uint8_t *getPointer(void) const { return bytes; }
-
- uint8_t bytes[SIZEOF_VALUE_BYTES];
- };
- //-------------------------------------------------------------------------------
- struct FlagSignalValueBytes {
- static const unsigned OFFSET_OF_FLAG = 0;
- static const unsigned OFFSET_OF_SIGNAL_QUALITY = 1;
- static const unsigned SIZEOF_VALUE_BYTES = 2;
-
- FlagSignalValueBytes() : bytes() {
- memset(bytes, 0x00, SIZEOF_VALUE_BYTES);
- }
-
- void updateFlagSignal(uint8_t statusFlag, uint8_t signalQuality) {
- bytes[OFFSET_OF_FLAG] = statusFlag;
- bytes[OFFSET_OF_SIGNAL_QUALITY] = signalQuality;
- }
-
- uint8_t *getPointer(void) { return bytes; }
- const uint8_t *getPointer(void) const { return bytes; }
-
- uint8_t bytes[SIZEOF_VALUE_BYTES];
- };
-//==================================================================================
-protected:
- BLE &ble;
-
- PlxSpotCheckMeasurementValueBytes plxMeasValueBytes;
- PlxFeaturesValueBytes plxFeatValueBytes;
- RawDataValueBytes rawValueBytes;
- FlagSignalValueBytes flagSigValueBytes;
-
- GattCharacteristic plxSpotCheckMeasurementCharacteristic;
- GattCharacteristic plxFeaturesCharacteristic;
- GattCharacteristic rawDataCharacteristic;
- GattCharacteristic signalCharacteristic;
-};
-
-#endif /* #ifndef __BLE_PULSE_OXIMETER_SERVICE_H__*/
\ No newline at end of file
--- a/main.cpp Fri Mar 31 08:05:22 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/* Copyright (c) 2016 MtM Technology Corporation, MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <events/mbed_events.h>
-#include <mbed.h>
-#include "ble/BLE.h"
-#include "ble/Gap.h"
-#include "ble/services/BatteryService.h"
-#include "ble/services/DeviceInformationService.h"
-#include "PulseOximeterService.h"
-#include "M1.h"
-
-/*
- * set 0 disable M1 data send to uart
- * 1 enable M1 data send to urat
- */
-#define M1_UART_RAW_DATA_ENABLE 0
-
-DigitalOut ledRed(p16, 1);
-Serial pc(p5, p4);
-I2C i2c(p3, p2);
-M1 m1(i2c);
-
-const static char DEVICE_NAME[] = "MtM_PLX";
-static const uint16_t uuid16_list[] = { 0x1822, /* UUID_PULSE_OXIMETER_SERVICE */
- GattService::UUID_BATTERY_SERVICE,
- GattService::UUID_DEVICE_INFORMATION_SERVICE};
-
-static PulseOximeterService* plxServicePtr;
-static BatteryService* batteryServicePtr;
-
-static EventQueue eventQueue(
- /* event count */ 16 * /* event size */ 32
-);
-
-
-void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
-{
- BLE::Instance().gap().startAdvertising();
-}
-
-void blinkCallback(void)
-{
- ledRed = !ledRed;
-}
-
-void plxCallback(void)
-{
- M1::Plx plx;
-
- BLE &ble = BLE::Instance();
- if (ble.gap().getState().connected && m1.IsSkinIn()) {
- m1.GetPlx(&plx);
- plxServicePtr->updatePlxMeas((float)plx.spo2, (float)plx.pulseRate);
- }
-}
-
-void rawCallback(void)
-{
- M1::Raw raw;
- static uint8_t cnt = 0;
- static uint8_t raw_x3[6*3];
-
- BLE &ble = BLE::Instance();
- if (ble.gap().getState().connected && m1.IsSkinIn()) {
- m1.GetRaw(&raw);
-
- raw_x3[6*cnt+0] = (uint8_t)(raw.red >> 8);
- raw_x3[6*cnt+1] = (uint8_t)(raw.red >> 0);
- raw_x3[6*cnt+2] = (uint8_t)(raw.ir >> 8);
- raw_x3[6*cnt+3] = (uint8_t)(raw.ir >> 0);
- raw_x3[6*cnt+4] = (uint8_t)(raw.green >> 8);
- raw_x3[6*cnt+5] = (uint8_t)(raw.green >> 0);
-
- if (++cnt >= 3) {
- plxServicePtr->updateRaw(raw_x3);
- cnt = 0;
- }
- } else {
- cnt = 0;
- }
-}
-
-void rawCallbackToUART() {
- M1::Raw raw;
- if(m1.IsSkinIn()) {
- m1.GetRaw(&raw);
- pc.printf("%d,%d,%d\r\n",raw.red, raw.ir, raw.green);
- }
-}
-
-void StatusCallback(void)
-{
- M1::Status sta;
-
- BLE &ble = BLE::Instance();
- if (ble.gap().getState().connected) {
- m1.GetStatus(&sta);
- plxServicePtr->updateStatusFlagAndSignalQuality(sta.flags, sta.signalQuality);
- }
-}
-
-void batteryCallback(void )
-{
- uint8_t batteryLevel = 99;
-
- BLE &ble = BLE::Instance();
- if (ble.gap().getState().connected) {
- batteryServicePtr->updateBatteryLevel(batteryLevel);
- }
-}
-
-/**
- * This function is called when the ble initialization process has failled
- */
-void onBleInitError(BLE &ble, ble_error_t error)
-{
- /* Initialization error handling should go here */
-}
-
-/**
- * Callback triggered when the ble initialization process has finished
- */
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
-{
- BLE& ble = params->ble;
- ble_error_t error = params->error;
-
- if (error != BLE_ERROR_NONE) {
- /* In case of error, forward the error handling to onBleInitError */
- onBleInitError(ble, error);
- return;
- }
-
- /* Ensure that it is the default instance of BLE */
- if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
- return;
- }
-
- ble.gap().onDisconnection(disconnectionCallback);
-
- /* Setup primary service */
- plxServicePtr = new PulseOximeterService(ble, 0, 0);
- batteryServicePtr = new BatteryService(ble, 100);
- DeviceInformationService deviceInfo(ble, "MtM");
-
- /* Setup advertising */
- ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
- ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *) uuid16_list, sizeof(uuid16_list));
- ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME));
- ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::PULSE_OXIMETER_GENERIC);
- ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
- ble.gap().setAdvertisingInterval(1000); /* 1000ms */
- ble.gap().startAdvertising();
-}
-
-void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
- BLE &ble = BLE::Instance();
- eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
-}
-
-int main()
-{
- /* Disable the hardware flow control of Serial, then show the mbed version */
- pc.set_flow_control(SerialBase::Disabled);
- pc.baud(115200);
- pc.printf("\r\n");
- pc.printf("mbed version(%d.%d.%d)\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
- pc.printf("\r\n");
-
- /* Config device */
- m1.ConfigDevice();
-
-#if M1_UART_RAW_DATA_ENABLE
- /* 35ms getter raw data to uart */
- eventQueue.call_every(35, rawCallbackToUART);
- eventQueue.call_every(500, blinkCallback);
-#else
- /* Update each data every N ms */
- eventQueue.call_every(1000, plxCallback);
- eventQueue.call_every(35, rawCallback);
- eventQueue.call_every(1000, StatusCallback);
- eventQueue.call_every(500, batteryCallback);
- eventQueue.call_every(500, blinkCallback);
-
- BLE &ble = BLE::Instance();
- ble.onEventsToProcess(scheduleBleEventsProcessing);
- ble.init(bleInitComplete);
-#endif
-
- eventQueue.dispatch_forever();
-
- return 0;
-}
\ No newline at end of file
--- a/mbed-os.lib Fri Mar 31 08:05:22 2017 +0000 +++ b/mbed-os.lib Fri Apr 27 09:59:38 2018 +0000 @@ -1,1 +1,1 @@ -https://github.com/ARMmbed/mbed-os/#bcf7085d85b2811b5d68bdda192c754eadfb8f88 +https://github.com/ARMmbed/mbed-os/#fc1836545dcc2fc86f03b01292b62bf2089f67c3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/source/PulseOximeterService.h Fri Apr 27 09:59:38 2018 +0000
@@ -0,0 +1,205 @@
+/* Copyright (c) 2016 MtM Technology Corporation, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __BLE_PULSE_OXIMETER_SERVICE_H__
+#define __BLE_PULSE_OXIMETER_SERVICE_H__
+
+#include "ble/BLE.h"
+
+class PulseOximeterService {
+public:
+ PulseOximeterService(BLE &_ble, float spo2, float pr) :
+ ble(_ble),
+ plxMeasValueBytes(spo2, pr),
+ plxFeatValueBytes(),
+ rawValueBytes(),
+ flagSigValueBytes(),
+ plxSpotCheckMeasurementCharacteristic(0x2A5E/* UUID:PLX Spot-Check Measurement */,
+ plxMeasValueBytes.getPointer(),
+ PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES,
+ PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES,
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE,
+ NULL, 0, false
+ ),
+ plxFeaturesCharacteristic(0x2A60/* UUID:PLX Features */,
+ plxFeatValueBytes.getPointer(),
+ PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES,
+ PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES,
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
+ NULL, 0, false
+ ),
+ rawDataCharacteristic(0x2B00/* UUID:Self defined for raw data */,
+ rawValueBytes.getPointer(),
+ RawDataValueBytes::SIZEOF_VALUE_BYTES,
+ RawDataValueBytes::SIZEOF_VALUE_BYTES,
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY,
+ NULL, 0, false
+ ),
+ signalCharacteristic(0x2B01/* UUID:Self defined for flag & signal */,
+ flagSigValueBytes.getPointer(),
+ FlagSignalValueBytes::SIZEOF_VALUE_BYTES,
+ FlagSignalValueBytes::SIZEOF_VALUE_BYTES,
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
+ NULL, 0, false
+ )
+ {
+ GattCharacteristic *charTable[] = {
+ &plxSpotCheckMeasurementCharacteristic,
+ &plxFeaturesCharacteristic,
+ &rawDataCharacteristic,
+ &signalCharacteristic
+ };
+ GattService PulseOximeterService(0x1822/* UUID:Pulse Oximeter Service */, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+ ble.gattServer().addService(PulseOximeterService);
+ }
+
+ void updatePlxMeas(float spo2, float pr) {
+ plxMeasValueBytes.updatePlxSpotCheckMeasurement(spo2, pr);
+ ble.gattServer().write(plxSpotCheckMeasurementCharacteristic.getValueHandle(),
+ plxMeasValueBytes.getPointer(),
+ PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES
+ );
+ }
+
+ void updateRaw(uint8_t *raw) {
+ rawValueBytes.updateRawData(raw);
+ ble.gattServer().write(rawDataCharacteristic.getValueHandle(),
+ rawValueBytes.getPointer(),
+ RawDataValueBytes::SIZEOF_VALUE_BYTES
+ );
+ }
+
+ void updateStatusFlagAndSignalQuality(uint8_t statusFlag, uint8_t signalQuality) {
+ flagSigValueBytes.updateFlagSignal(statusFlag, signalQuality);
+ ble.gattServer().write(signalCharacteristic.getValueHandle(),
+ flagSigValueBytes.getPointer(),
+ FlagSignalValueBytes::SIZEOF_VALUE_BYTES
+ );
+ }
+//==================================================================================
+private:
+ struct PlxSpotCheckMeasurementValueBytes {
+ static const unsigned OFFSET_OF_FLAGS = 0;
+ static const unsigned OFFSET_OF_SPO2 = 1;
+ static const unsigned OFFSET_OF_PR = 3;
+ static const unsigned SIZEOF_VALUE_BYTES = 5;
+
+ PlxSpotCheckMeasurementValueBytes(float spo2, float pr) : bytes() {
+ bytes[OFFSET_OF_FLAGS] = 0x00; /* All fields aren't present */
+ updatePlxSpotCheckMeasurement(spo2, pr);
+ }
+
+ void updatePlxSpotCheckMeasurement(float spo2, float pr) {
+ uint16_t sfloat_spo2 = ieee11073_SFLOAT(spo2);
+ uint16_t sfloat_pr = ieee11073_SFLOAT(pr);
+#if 0
+ memcpy(&bytes[OFFSET_OF_SPO2], &sfloat_spo2, sizeof(uint16_t));
+ memcpy(&bytes[OFFSET_OF_PR], &sfloat_pr, sizeof(uint16_t));
+#else
+ bytes[OFFSET_OF_SPO2+0] = (uint8_t)(sfloat_spo2 >> 8);
+ bytes[OFFSET_OF_SPO2+1] = (uint8_t)(sfloat_spo2 >> 0);
+ bytes[OFFSET_OF_PR+0] = (uint8_t)(sfloat_pr >> 8);
+ bytes[OFFSET_OF_PR+1] = (uint8_t)(sfloat_pr >> 0);
+#endif
+ }
+
+ uint8_t *getPointer(void) { return bytes; }
+ const uint8_t *getPointer(void) const { return bytes; }
+
+ uint16_t ieee11073_SFLOAT(float v) {
+ /* Bitmap: eeee_mmmm_mmmm_mmmm */
+ /* Exponent: 4bits, Base10, 2'sComplement */
+ /* Mantissa: 12bits, 2's Complement */
+ uint8_t exponent = 0;
+ uint16_t mantissa = (uint16_t)v;
+ return (((uint16_t)exponent) << 12) | mantissa;
+ }
+
+ uint8_t bytes[SIZEOF_VALUE_BYTES];
+ };
+ //-------------------------------------------------------------------------------
+ struct PlxFeaturesValueBytes {
+ static const unsigned OFFSET_OF_SUPPORTED_FEATURES = 0;
+ static const unsigned SIZEOF_VALUE_BYTES = 2;
+
+ PlxFeaturesValueBytes() : bytes() {
+ memset(bytes, 0x00, SIZEOF_VALUE_BYTES); /* All features aren't support */
+ }
+
+ void updatePlxFeatures(uint16_t feat) {
+ memcpy(&bytes[OFFSET_OF_SUPPORTED_FEATURES], &feat, SIZEOF_VALUE_BYTES);
+ }
+
+ uint8_t *getPointer(void) { return bytes; }
+ const uint8_t *getPointer(void) const { return bytes; }
+
+ uint8_t bytes[SIZEOF_VALUE_BYTES];
+ };
+ //-------------------------------------------------------------------------------
+ struct RawDataValueBytes {
+ static const unsigned OFFSET_OF_RAW = 0;
+ static const unsigned SIZEOF_VALUE_BYTES = 18;
+
+ RawDataValueBytes() : bytes() {
+ memset(bytes, 0x00, SIZEOF_VALUE_BYTES);
+ }
+
+ void updateRawData(uint8_t *raw) {
+ memcpy(&bytes[OFFSET_OF_RAW], raw, SIZEOF_VALUE_BYTES);
+ }
+
+ uint8_t *getPointer(void) { return bytes; }
+ const uint8_t *getPointer(void) const { return bytes; }
+
+ uint8_t bytes[SIZEOF_VALUE_BYTES];
+ };
+ //-------------------------------------------------------------------------------
+ struct FlagSignalValueBytes {
+ static const unsigned OFFSET_OF_FLAG = 0;
+ static const unsigned OFFSET_OF_SIGNAL_QUALITY = 1;
+ static const unsigned SIZEOF_VALUE_BYTES = 2;
+
+ FlagSignalValueBytes() : bytes() {
+ memset(bytes, 0x00, SIZEOF_VALUE_BYTES);
+ }
+
+ void updateFlagSignal(uint8_t statusFlag, uint8_t signalQuality) {
+ bytes[OFFSET_OF_FLAG] = statusFlag;
+ bytes[OFFSET_OF_SIGNAL_QUALITY] = signalQuality;
+ }
+
+ uint8_t *getPointer(void) { return bytes; }
+ const uint8_t *getPointer(void) const { return bytes; }
+
+ uint8_t bytes[SIZEOF_VALUE_BYTES];
+ };
+//==================================================================================
+protected:
+ BLE &ble;
+
+ PlxSpotCheckMeasurementValueBytes plxMeasValueBytes;
+ PlxFeaturesValueBytes plxFeatValueBytes;
+ RawDataValueBytes rawValueBytes;
+ FlagSignalValueBytes flagSigValueBytes;
+
+ GattCharacteristic plxSpotCheckMeasurementCharacteristic;
+ GattCharacteristic plxFeaturesCharacteristic;
+ GattCharacteristic rawDataCharacteristic;
+ GattCharacteristic signalCharacteristic;
+};
+
+#endif /* #ifndef __BLE_PULSE_OXIMETER_SERVICE_H__*/
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/source/main.cpp Fri Apr 27 09:59:38 2018 +0000
@@ -0,0 +1,213 @@
+/* Copyright (c) 2016 MtM Technology Corporation, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <events/mbed_events.h>
+#include <mbed.h>
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ble/services/BatteryService.h"
+#include "ble/services/DeviceInformationService.h"
+#include "PulseOximeterService.h"
+#include "M1.h"
+
+/*
+ * set 0 disable M1 data send to uart
+ * 1 enable M1 data send to urat
+ */
+#define M1_UART_RAW_DATA_ENABLE 0
+
+DigitalOut ledRed(p16, 1);
+#ifdef NRF52
+Serial pc(p20, p24);
+#else
+Serial pc(p5, p4);
+#endif
+I2C i2c(p3, p2);
+M1 m1(i2c);
+
+const static char DEVICE_NAME[] = "Mt5MtSense06";
+static const uint16_t uuid16_list[] = { 0x1822, /* UUID_PULSE_OXIMETER_SERVICE */
+ GattService::UUID_BATTERY_SERVICE,
+ GattService::UUID_DEVICE_INFORMATION_SERVICE};
+
+static PulseOximeterService* plxServicePtr;
+static BatteryService* batteryServicePtr;
+
+static EventQueue eventQueue(
+ /* event count */ 16 * /* event size */ 32
+);
+
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+ BLE::Instance().gap().startAdvertising();
+}
+
+void blinkCallback(void)
+{
+ ledRed = !ledRed;
+}
+
+void plxCallback(void)
+{
+ M1::Plx plx;
+
+ BLE &ble = BLE::Instance();
+ if (ble.gap().getState().connected && m1.IsSkinIn()) {
+ m1.GetPlx(&plx);
+ plxServicePtr->updatePlxMeas((float)plx.spo2, (float)plx.pulseRate);
+ }
+}
+
+void rawCallback(void)
+{
+ M1::Raw raw;
+ static uint8_t cnt = 0;
+ static uint8_t raw_x3[6*3];
+
+ BLE &ble = BLE::Instance();
+ if (ble.gap().getState().connected && m1.IsSkinIn()) {
+ m1.GetRaw(&raw);
+
+ raw_x3[6*cnt+0] = (uint8_t)(raw.red >> 8);
+ raw_x3[6*cnt+1] = (uint8_t)(raw.red >> 0);
+ raw_x3[6*cnt+2] = (uint8_t)(raw.ir >> 8);
+ raw_x3[6*cnt+3] = (uint8_t)(raw.ir >> 0);
+ raw_x3[6*cnt+4] = (uint8_t)(raw.green >> 8);
+ raw_x3[6*cnt+5] = (uint8_t)(raw.green >> 0);
+
+ if (++cnt >= 3) {
+ plxServicePtr->updateRaw(raw_x3);
+ cnt = 0;
+ }
+ } else {
+ cnt = 0;
+ }
+}
+
+void rawCallbackToUART() {
+ M1::Raw raw;
+ if(m1.IsSkinIn()) {
+ m1.GetRaw(&raw);
+ pc.printf("%d,%d,%d\r\n",raw.red, raw.ir, raw.green);
+ }
+}
+
+void StatusCallback(void)
+{
+ M1::Status sta;
+
+ BLE &ble = BLE::Instance();
+ if (ble.gap().getState().connected) {
+ m1.GetStatus(&sta);
+ plxServicePtr->updateStatusFlagAndSignalQuality(sta.flags, sta.signalQuality);
+ }
+}
+
+void batteryCallback(void )
+{
+ uint8_t batteryLevel = 99;
+
+ BLE &ble = BLE::Instance();
+ if (ble.gap().getState().connected) {
+ batteryServicePtr->updateBatteryLevel(batteryLevel);
+ }
+}
+
+/**
+ * This function is called when the ble initialization process has failled
+ */
+void onBleInitError(BLE &ble, ble_error_t error)
+{
+ /* Initialization error handling should go here */
+}
+
+/**
+ * Callback triggered when the ble initialization process has finished
+ */
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
+{
+ BLE& ble = params->ble;
+ ble_error_t error = params->error;
+
+ if (error != BLE_ERROR_NONE) {
+ /* In case of error, forward the error handling to onBleInitError */
+ onBleInitError(ble, error);
+ return;
+ }
+
+ /* Ensure that it is the default instance of BLE */
+ if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
+ return;
+ }
+
+ ble.gap().onDisconnection(disconnectionCallback);
+
+ /* Setup primary service */
+ plxServicePtr = new PulseOximeterService(ble, 0, 0);
+ batteryServicePtr = new BatteryService(ble, 100);
+ DeviceInformationService deviceInfo(ble, "MtM");
+
+ /* Setup advertising */
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *) uuid16_list, sizeof(uuid16_list));
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME));
+ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::PULSE_OXIMETER_GENERIC);
+ ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+ ble.gap().setAdvertisingInterval(1000); /* 1000ms */
+ ble.gap().startAdvertising();
+}
+
+void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
+ BLE &ble = BLE::Instance();
+ eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
+}
+
+int main()
+{
+ /* Disable the hardware flow control of Serial, then show the mbed version */
+ pc.set_flow_control(SerialBase::Disabled);
+ pc.baud(115200);
+ pc.printf("\r\n");
+ pc.printf("mbed version(%d.%d.%d)\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
+ pc.printf("\r\n");
+
+ /* Config device */
+ m1.ConfigDevice();
+
+#if M1_UART_RAW_DATA_ENABLE
+ /* 35ms getter raw data to uart */
+ eventQueue.call_every(35, rawCallbackToUART);
+ eventQueue.call_every(500, blinkCallback);
+#else
+ /* Update each data every N ms */
+ eventQueue.call_every(1000, plxCallback);
+ eventQueue.call_every(35, rawCallback);
+ eventQueue.call_every(1000, StatusCallback);
+ eventQueue.call_every(500, batteryCallback);
+ eventQueue.call_every(500, blinkCallback);
+#endif
+
+ BLE &ble = BLE::Instance();
+ ble.onEventsToProcess(scheduleBleEventsProcessing);
+ ble.init(bleInitComplete);
+
+
+ eventQueue.dispatch_forever();
+
+ return 0;
+}
\ No newline at end of file
