Icarus Sensors / Mbed 2 deprecated Cycle_Speed_Cadence_Service

Dependencies:   BLE_API mbed nRF51822

Fork of Bluetooth_Heart_Rate_Monitor_dummy by Icarus Sensors

Revision:
61:16f888838853
Child:
62:2ea9997b5249
diff -r 9fd2b0b43718 -r 16f888838853 CycleSpeedCadenceService.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CycleSpeedCadenceService.h	Mon May 04 17:18:12 2015 +0000
@@ -0,0 +1,269 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BLE_CYCLE_SPEED_CADENCE_SERVICE_H__
+#define __BLE_CYCLE_SPEED_CADENCE_SERVICE_H__
+
+#include "BLEDevice.h"
+
+/**
+* @class CycleSpeedCadenceService
+* @brief BLE Service for HeartRate. This BLE Service contains the location of the sensor, the heartrate in beats per minute. <br>
+* Service:  https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml <br>
+* HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml <br>
+* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml
+*/
+class CycleSpeedCadenceService {
+public:
+    /**
+    * @enum SensorLocation
+    * @brief Location of HeartRate sensor on body.
+    */
+    enum {
+        LOCATION_OTHER = 0, 
+        LOCATION_TOP_OF_SHOE,
+        LOCATION_IN_SHOE,
+        LOCATION_HIP,    
+        LOCATION_FRONT_WHEEL,
+        LOCATION_LEFT_CRANK,
+        LOCATION_RIGHT_CRANK,
+        LOCATION_LEFT_PEDAL,
+        LOCATION_RIGHT_PEDAL,
+        LOCATION_FRONT_HUB,
+        LOCATION_REAR_DROPOUT,
+        LOCATION_CHAINSTAY,
+        LOCATION_REAR_WHEEL,
+        LOCATION_REAR_HUB,
+        LOCATION_CHEST
+    };
+    
+    enum {
+         UUID_SENSOR_LOCATION_CHAR = 0x2A5D,
+         UUID_CSC_MEASUREMENT_CHAR = 0x2A5B,
+         UUID_CSC_FEATURE_CHAR = 0x2A5C
+    };
+    
+    
+
+public:
+    /**
+     * @brief Constructor with 8bit HRM Counter value.
+     *
+     * @param[ref] _ble
+     *               Reference to the underlying BLEDevice.
+     * @param[in] hrmCounter (8-bit)
+     *               initial value for the hrm counter.
+     * @param[in] location
+     *               Sensor's location.
+     */
+    CycleSpeedCadenceService(BLEDevice &_ble, uint32_t wheelRevolutions ,uint16_t wheelEvent, uint8_t location, bool locationSupport) :
+        ble(_ble),
+        feautureBytes(true,false,locationSupport),
+        valueBytes(wheelRevolutions,wheelEvent),
+        cscMesurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
+                valueBytes.getNumValueBytes(), CSCValueBytes::MAX_VALUE_BYTES,
+                GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        cscFeatures(CycleSpeedCadenceService::UUID_CSC_FEATURE_CHAR, feautureBytes.getPointer()),
+        sensorLocation(CycleSpeedCadenceService::UUID_SENSOR_LOCATION_CHAR, &location),        
+        controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
+        setupService();
+    }
+
+    CycleSpeedCadenceService(BLEDevice &_ble, uint16_t crankRevolutions, uint16_t crankEvent, uint8_t location, bool locationSupport ) :
+        ble(_ble),
+        feautureBytes(false,true,locationSupport),
+        valueBytes(crankRevolutions,crankEvent),
+        cscMesurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
+                valueBytes.getNumValueBytes(), CSCValueBytes::MAX_VALUE_BYTES,
+                GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        cscFeatures(CycleSpeedCadenceService::UUID_CSC_FEATURE_CHAR, feautureBytes.getPointer()),
+        sensorLocation(CycleSpeedCadenceService::UUID_SENSOR_LOCATION_CHAR, &location),        
+        controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
+        setupService();
+    }
+    
+    CycleSpeedCadenceService(BLEDevice &_ble, uint32_t wheelRevolutions ,uint16_t wheelEvent,uint16_t crankRevolutions, uint16_t crankEvent, uint8_t location,bool locationSupport ) :
+        ble(_ble),
+        feautureBytes(true,true,locationSupport),
+        valueBytes(wheelRevolutions,wheelEvent,crankRevolutions,crankEvent),
+        cscMesurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
+                valueBytes.getNumValueBytes(), CSCValueBytes::MAX_VALUE_BYTES,
+                GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        cscFeatures(CycleSpeedCadenceService::UUID_CSC_FEATURE_CHAR, feautureBytes.getPointer()),
+        sensorLocation(CycleSpeedCadenceService::UUID_SENSOR_LOCATION_CHAR, &location),        
+        controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
+        setupService();
+    }    
+
+    /**
+     * @brief Set a new 8-bit value for heart rate.
+     *
+     * @param[in] hrmCounter
+     *                  HeartRate in bpm.
+     */
+    void updateWheel(uint32_t wheelRevolutions ,uint16_t wheelEvent) {
+        valueBytes.updateWheel(wheelRevolutions,wheelEvent);
+        ble.updateCharacteristicValue(cscMesurement.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
+    }
+
+    /**
+     * Set a new 16-bit value for heart rate.
+     *
+     * @param[in] hrmCounter
+     *                  HeartRate in bpm.
+     */
+    void updateCrank(uint16_t crankRevolutions, uint16_t crankEvent) {
+        valueBytes.updateCrank(crankRevolutions,crankEvent);
+        ble.updateCharacteristicValue(cscMesurement.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
+    }
+
+    /**
+     * This callback allows the CycleSpeedCadenceService to receive updates to the
+     * controlPoint Characteristic.
+     *
+     * @param[in] params
+     *     Information about the characterisitc being updated.
+     */
+    virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
+        if (params->charHandle == controlPoint.getValueAttribute().getHandle()) {
+            /* Do something here if the new value is 1; else you can override this method by
+             * extending this class.
+             * @NOTE: if you are extending this class, be sure to also call
+             * ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in
+             * your constructor.
+             */
+        }
+    }
+
+private:
+    void setupService(void) {
+        static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
+        if (serviceAdded) {
+            return;
+        }
+
+        GattCharacteristic *charTable[] = {&cscMesurement, &cscFeatures, &sensorLocation, &controlPoint};
+        GattService         cscsService(GattService::UUID_CYCLING_SPEED_AND_CADENCE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+        ble.addService(cscsService);
+        serviceAdded = true;
+
+        ble.onDataWritten(this, &CycleSpeedCadenceService::onDataWritten);
+    }
+
+private:
+    struct CSCFeatureBytes {
+        uint16_t            cscFeaturesValue;
+        
+        CSCFeatureBytes(bool wheelSupport, bool crankSupport, bool locationSupport){
+            cscFeaturesValue= wheelSupport | crankSupport << 1 | locationSupport << 2;
+        }
+        
+        uint16_t       *getPointer(void) {
+            return &cscFeaturesValue;
+        }
+
+        const uint16_t *getPointer(void) const {
+            return &cscFeaturesValue;
+        }
+    };
+    /* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */
+    struct CSCValueBytes {
+        static const unsigned MAX_VALUE_BYTES  = 11; /* FLAGS + up to two bytes for heart-rate */
+        static const unsigned FLAGS_BYTE_INDEX = 0;
+        static const unsigned WHEEL_REVOLUTIONS_INDEX = 1;
+        static const unsigned WHEEL_EVENT_INDEX = 5;
+        static const unsigned CRANK_REVOLUTIONS_INDEX = 1;
+        static const unsigned CRANK_EVENT_INDEX = 3;
+        
+
+        static const unsigned WHEEL_PRESENCE_BITNUM = 0;        
+        static const uint8_t  WHEEL_FLAG   = (1 << WHEEL_PRESENCE_BITNUM);
+        static const unsigned CADENCE_PRESENCE_BITNUM = 0;
+        static const uint8_t  CADENCE_FLAG   = (1 << CADENCE_PRESENCE_BITNUM);
+
+        //speed
+        CSCValueBytes(uint32_t wheelRevolutions ,uint16_t wheelEvent) : valueBytes() {
+            valueBytes[FLAGS_BYTE_INDEX] &= WHEEL_FLAG;
+            updateWheel(wheelRevolutions,wheelEvent);
+        }
+        //cadence
+        CSCValueBytes(uint16_t crankRevolutions, uint16_t crankEvent ) : valueBytes() {
+            valueBytes[FLAGS_BYTE_INDEX] &= CADENCE_FLAG;
+            updateCrank(crankRevolutions,crankEvent);
+        }
+
+        //speed + cadence
+        CSCValueBytes(uint32_t wheelRevolutions ,uint16_t wheelEvent,uint16_t crankRevolutions, uint16_t crankEvent) : valueBytes() {
+            valueBytes[FLAGS_BYTE_INDEX] &= (WHEEL_FLAG |CADENCE_FLAG);
+            updateWheel(wheelRevolutions,wheelEvent);
+            updateCrank(crankRevolutions,crankEvent);
+        }
+                
+        
+        void updateWheel(uint32_t wheelRevolutions ,uint16_t wheelEvent) {
+            
+            valueBytes[WHEEL_REVOLUTIONS_INDEX] = (uint8_t)(wheelRevolutions & 0xFF);
+            valueBytes[WHEEL_REVOLUTIONS_INDEX + 1] = (uint8_t)((wheelRevolutions >> 8) & 0xFF);
+            valueBytes[WHEEL_REVOLUTIONS_INDEX + 2] = (uint8_t)((wheelRevolutions >> 16) & 0xFF);
+            valueBytes[WHEEL_REVOLUTIONS_INDEX + 3] = (uint8_t)((wheelRevolutions >> 24) & 0xFF);
+            valueBytes[WHEEL_EVENT_INDEX] = (uint8_t)(wheelEvent & 0xFF);
+            valueBytes[WHEEL_EVENT_INDEX + 1] = (uint8_t)((wheelEvent >> 8) & 0xFF);
+        }
+
+        void updateCrank(uint16_t crankRevolutions, uint16_t crankEvent) {
+            int offset = (valueBytes[FLAGS_BYTE_INDEX] & WHEEL_FLAG) ? sizeof(uint32_t)+ sizeof(uint16_t):0;
+            valueBytes[offset + CRANK_REVOLUTIONS_INDEX]    = (uint8_t)(crankRevolutions & 0xFF);
+            valueBytes[offset + CRANK_REVOLUTIONS_INDEX + 1] = (uint8_t)((crankRevolutions >> 8) & 0xFF);
+            valueBytes[offset + CRANK_EVENT_INDEX] = (uint8_t)(crankEvent & 0xFF);
+            valueBytes[offset + CRANK_EVENT_INDEX + 1] = (uint8_t)((crankEvent >> 8) & 0xFF);
+        }
+
+        uint8_t       *getPointer(void) {
+            return valueBytes;
+        }
+
+        const uint8_t *getPointer(void) const {
+            return valueBytes;
+        }
+
+        unsigned       getNumValueBytes(void) const {
+            return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & WHEEL_FLAG) ? sizeof(uint32_t)+ sizeof(uint16_t):0) 
+                     + ((valueBytes[FLAGS_BYTE_INDEX] & CADENCE_FLAG) ? sizeof(uint16_t) + sizeof(uint16_t):0);
+        }
+
+private:
+        /* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */
+        /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
+        uint8_t valueBytes[MAX_VALUE_BYTES];
+    };
+
+private:
+    BLEDevice           &ble;
+
+    CSCFeatureBytes       feautureBytes;
+    CSCValueBytes       valueBytes;
+    
+    uint8_t              controlPointValue;
+    
+
+    GattCharacteristic                   cscMesurement;
+    ReadOnlyGattCharacteristic<uint16_t>  cscFeatures;
+    ReadOnlyGattCharacteristic<uint8_t>  sensorLocation;
+    WriteOnlyGattCharacteristic<uint8_t> controlPoint;
+};
+
+#endif /* #ifndef __BLE_CYCLE_SPEED_CADENCE_SERVICE_H__*/
\ No newline at end of file