Cycle speed and cadence example for the BLE API using nRF51822 native mode drivers

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_HeartRate by Bluetooth Low Energy

Revision:
73:bae88c99c2ae
Parent:
72:a15b8451829f
Child:
74:98dee483c173
diff -r a15b8451829f -r bae88c99c2ae CyclingSpeedAndCadenceService.h
--- a/CyclingSpeedAndCadenceService.h	Sun Aug 16 14:46:43 2015 +0000
+++ b/CyclingSpeedAndCadenceService.h	Sun Aug 23 14:00:28 2015 +0000
@@ -28,6 +28,12 @@
 */
 class CyclingSpeedAndCadenceService {
 public:
+    enum Mode {
+        MODE_SPEED,
+        MODE_CADENCE,
+        MODE_SPEED_CADENCE
+    };
+    
     /**
     * @enum SensorLocation
     * @brief Location of sensor on bike.
@@ -68,13 +74,15 @@
      * @param[in] location
      *               Sensor's location.
      */
-    CyclingSpeedAndCadenceService(BLE &_ble, uint8_t location) :
+    CyclingSpeedAndCadenceService(BLE &_ble, Mode _mode, uint8_t location) :
         ble(_ble),
-        feature(3),            
-        csc(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
-            valueBytes.getNumValueBytes(), SpeedCadenceValueBytes::MAX_BYTES,
+        value(_mode),     
+        mode(_mode),
+        csc(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR,
+            value.bytes,
+            value.getSize(), value.getSize(),
             GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
-        cscFeat(GattCharacteristic::UUID_CSC_FEATURE_CHAR, (uint8_t*)&feature,
+        cscFeat(GattCharacteristic::UUID_CSC_FEATURE_CHAR, (uint8_t*)&mode,
             2, 2,
             GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
         scLocation(UUID_SENSOR_LOCATION_CHAR, &location),
@@ -90,9 +98,10 @@
      * @param[in] eventTime
      *                  Time of event.
      */
-    void updateWheelCounter(uint32_t wheelCounter, uint16_t eventTime) {
-        valueBytes.updateWheelCounter(wheelCounter, eventTime);
-        ble.gattServer().write(csc.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
+    void updateWheelCounter(uint32_t wheelCounter, uint16_t eventTime)
+    {
+        value.updateWheelCounter(wheelCounter, eventTime);
+        sendUpdate();
     }
 
     /**
@@ -103,15 +112,16 @@
      * @param[in] eventTime
      *                  Time of event.
      */
-    void updateCrankCounter(uint16_t crankCounter, uint16_t eventTime) {
-        valueBytes.updateCrankCounter(crankCounter, eventTime);
-        ble.gattServer().write(csc.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
+    void updateCrankCounter(uint16_t crankCounter, uint16_t eventTime)
+    {
+        value.updateCrankCounter(crankCounter, eventTime);
+        sendUpdate();
     }
 
-    void updateCounters(uint32_t wheelCounter, uint16_t crankCounter, uint16_t eventTime) {
-        valueBytes.updateWheelCounter(wheelCounter, eventTime);
-        valueBytes.updateCrankCounter(crankCounter, eventTime);
-        ble.gattServer().write(csc.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
+    void updateCounters(uint32_t wheelCounter, uint16_t crankCounter, uint16_t eventTime)
+    {
+        value.updateCounters(wheelCounter, crankCounter, eventTime);
+        sendUpdate();
     }
 
     /**
@@ -141,80 +151,133 @@
         ble.onDataWritten(this, &CyclingSpeedAndCadenceService::onDataWritten);
     }
 
-protected:
-    /* Private internal representation for the bytes used to work with the value of the speed cadence characteristic. */
-    struct SpeedCadenceValueBytes {
-        static const uint16_t MAX_BYTES = (1 + 4 + 2 + 2 + 2);
-        static const uint8_t FLAG_WHEEL_PRESENT = (1 << 0);
-        static const uint8_t FLAG_CRANK_PRESENT = (1 << 1);
 
-        SpeedCadenceValueBytes()
-            : flags(0)
-        {
-            updateWheelCounter(1, 0);
-            updateCrankCounter(1, 0);
-        }
-
-        void updateWheelCounter(uint32_t _wheelCounter, uint16_t _when) {
-            flags |= FLAG_WHEEL_PRESENT;
-            wheelCounter = _wheelCounter;
-            lastWheelEvent = _when;
-            pack();
-        }
-
-        void updateCrankCounter(uint16_t _crankCounter, uint16_t _when) {
-            flags |= FLAG_CRANK_PRESENT;
-            crankCounter = _crankCounter;
-            lastCrankEvent = _when;
-            pack();
-        }
+    void sendUpdate()
+    {            
+        ble.gattServer().write(csc.getValueHandle(), value.bytes, value.getSize());
+    }
 
-        uint8_t       *getPointer(void) {
-            return valueBytes;
-        }
-
-        unsigned       getNumValueBytes(void) const {
-            return 1 +
-                ((flags & FLAG_WHEEL_PRESENT) ? (4+2) : 0) +
-                ((flags & FLAG_CRANK_PRESENT) ? (2+2) : 0);
-        }
-
-    private:
-        void pack()
+protected:
+    static const uint8_t FLAG_WHEEL_PRESENT = (1 << 0);
+    static const uint8_t FLAG_CRANK_PRESENT = (1 << 1);
+    static const uint16_t MAX_BYTES = (1 + 4 + 2 + 2 + 2);
+    union SpeedCadenceValue
+    {
+        SpeedCadenceValue(uint16_t mode)
         {
-            valueBytes[0] = flags;
-            unsigned p = 1;
-            if (flags & FLAG_WHEEL_PRESENT)
+            switch (mode)
             {
-                valueBytes[p++] = wheelCounter & 0xFF;
-                valueBytes[p++] = (wheelCounter >>  8) & 0xFF;
-                valueBytes[p++] = (wheelCounter >> 16) & 0xFF;
-                valueBytes[p++] = (wheelCounter >> 24) & 0xFF;
-                valueBytes[p++] = lastWheelEvent & 0xFF;
-                valueBytes[p++] = (lastWheelEvent >>  8) & 0xFF;
-            }
-            if (flags & FLAG_CRANK_PRESENT)
-            {
-                valueBytes[p++] = crankCounter & 0xFF;
-                valueBytes[p++] = (crankCounter >>  8) & 0xFF;
-                valueBytes[p++] = lastCrankEvent & 0xFF;
-                valueBytes[p++] = (lastCrankEvent >>  8) & 0xFF;
+            case MODE_SPEED:
+                v.flags = FLAG_WHEEL_PRESENT;
+                break;
+            case MODE_CADENCE:
+                v.flags = FLAG_CRANK_PRESENT;
+                break;
+            case MODE_SPEED_CADENCE:
+                v.flags = FLAG_WHEEL_PRESENT | FLAG_CRANK_PRESENT;
+                break;
+            default:
+                v.flags = 0;
+                break;
             }
         }
         
-        uint8_t flags;
-        uint32_t wheelCounter;
-        uint16_t lastWheelEvent;
-        uint16_t crankCounter;
-        uint16_t lastCrankEvent;
-        uint8_t valueBytes[MAX_BYTES];
+        void updateWheelCounter(uint32_t wheelCounter, uint16_t eventTime)
+        {
+            switch(v.flags)
+            {
+            case FLAG_WHEEL_PRESENT:
+                v.v.speed.wheelCounter = wheelCounter;
+                v.v.speed.lastWheelEvent = eventTime;
+                break;
+            case FLAG_WHEEL_PRESENT | FLAG_CRANK_PRESENT:
+                v.v.speedCadence.wheelCounter = wheelCounter;
+                v.v.speedCadence.lastWheelEvent = eventTime;
+                break;
+            default:
+                break;
+            }
+        }
+
+        void updateCrankCounter(uint16_t crankCounter, uint16_t eventTime)
+        {
+            switch(v.flags)
+            {
+            case FLAG_CRANK_PRESENT:
+                v.v.cadence.crankCounter = crankCounter;
+                v.v.cadence.lastCrankEvent = eventTime;
+                break;
+            case FLAG_WHEEL_PRESENT | FLAG_CRANK_PRESENT:
+                v.v.speedCadence.crankCounter = crankCounter;
+                v.v.speedCadence.lastCrankEvent = eventTime;
+                break;
+            default:
+                break;
+            }
+        }
+
+        void updateCounters(uint32_t wheelCounter, uint16_t crankCounter, uint16_t eventTime)
+        {
+            switch(v.flags)
+            {
+            case FLAG_WHEEL_PRESENT:
+                v.v.speed.wheelCounter = wheelCounter;
+                v.v.speed.lastWheelEvent = eventTime;
+                break;
+            case FLAG_CRANK_PRESENT:
+                v.v.cadence.crankCounter = crankCounter;
+                v.v.cadence.lastCrankEvent = eventTime;
+                break;
+            case FLAG_WHEEL_PRESENT | FLAG_CRANK_PRESENT:
+                v.v.speedCadence.wheelCounter = wheelCounter;
+                v.v.speedCadence.lastWheelEvent = eventTime;
+                v.v.speedCadence.crankCounter = crankCounter;
+                v.v.speedCadence.lastCrankEvent = eventTime;
+                break;
+            default:
+                break;
+            }
+        }
+
+        uint16_t getSize()
+        {
+            return 1 +
+                ((v.flags & FLAG_WHEEL_PRESENT) ? (4+2) : 0) +
+                ((v.flags & FLAG_CRANK_PRESENT) ? (2+2) : 0);
+        }
+        
+        __packed struct Value
+        {        
+            uint8_t flags;
+            __packed union
+            {
+                __packed struct Speed
+                {
+                    uint32_t wheelCounter;
+                    uint16_t lastWheelEvent;
+                } speed;
+                __packed struct Cadence
+                {
+                    uint16_t crankCounter;
+                    uint16_t lastCrankEvent;
+                } cadence;
+                __packed struct SpeedCadence
+                {
+                    uint32_t wheelCounter;
+                    uint16_t lastWheelEvent;
+                    uint16_t crankCounter;
+                    uint16_t lastCrankEvent;
+                } speedCadence;
+            } v;
+        } v;
+        uint8_t bytes[1+4+2+2+2];
     };
 
 protected:
     BLE                 &ble;
 
-    SpeedCadenceValueBytes  valueBytes;
-    uint16_t             feature;
+    SpeedCadenceValue    value;
+    uint16_t             mode;
     uint8_t              controlPointValue;
 
     GattCharacteristic                   csc;