Firmware for Keewi v1 electronic board

Dependencies:   BLE_API mbed nRF51822

Fork of Keewi_v1 by Clément Bertolini

Files at this revision

API Documentation at this revision

Comitter:
clemberto
Date:
Fri Jul 18 10:42:51 2014 +0000
Parent:
0:4f6fbeb69f11
Child:
2:8ebada2e4924
Commit message:
CSC profile connecting

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BLE_API.lib	Thu Jul 17 15:23:32 2014 +0000
+++ b/BLE_API.lib	Fri Jul 18 10:42:51 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#8890715aaf55
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#c163aa495b58
--- a/main.cpp	Thu Jul 17 15:23:32 2014 +0000
+++ b/main.cpp	Fri Jul 18 10:42:51 2014 +0000
@@ -20,45 +20,129 @@
 BLEDevice  ble;
 DigitalOut led1(LED1);
 
-#define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console;
+#define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
                                * it will have an impact on code-size and power consumption. */
 
 #if NEED_CONSOLE_OUTPUT
 Serial  pc(USBTX, USBRX);
+
 #define DEBUG(...) { pc.printf(__VA_ARGS__); }
 #else
 #define DEBUG(...) /* nothing */
 #endif /* #if NEED_CONSOLE_OUTPUT */
 
-const static char  DEVICE_NAME[] = "Keewi_v1";
+const static char  DEVICE_NAME[] = "Keewi v1";
 
-/* Heart Rate Service */
+// DEVICE_NAME_UUID = '2A00'; // Nordic fixed this to nRF5, can be written
+ 
+// Temperature 0-100 C, simulated
+static uint8_t      temperature = 32;
+GattCharacteristic  tempMeas(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, (uint8_t *)temperature, sizeof(temperature), sizeof(temperature),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+GattCharacteristic *temperatureChars[] = {&tempMeas };
+// TODO: config service Health thermo
+GattService         temperatureService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, temperatureChars, sizeof(temperatureChars) / sizeof(GattCharacteristic *));
+ 
+// SYSTEM
+static char         systemId = 'A';
+GattCharacteristic  systemID(GattCharacteristic::UUID_SYSTEM_ID_CHAR, (uint8_t *)systemId, sizeof(systemId), sizeof(systemId),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *systemChars[] = {&systemID };
+GattService         systemService(GattService::UUID_DEVICE_INFORMATION_SERVICE, systemChars, sizeof(systemChars) / sizeof(GattCharacteristic *));
+ 
+// MODEL
+static char         model[31] = "mBed nRF51822";
+GattCharacteristic  modelID(GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR, (uint8_t *)model, sizeof(model), sizeof(model),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *modelChars[] = {&modelID };
+GattService         modelService(GattService::UUID_DEVICE_INFORMATION_SERVICE, modelChars, sizeof(modelChars) / sizeof(GattCharacteristic *));
+ 
+// Firmware
+static char         fwversion[31] = "Firmware: 0216";
+GattCharacteristic  fwChars(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR, (uint8_t *)fwversion, sizeof(fwversion), sizeof(fwversion),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *firmwareChars[] = {&fwChars };
+GattService         firmwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, firmwareChars, sizeof(firmwareChars) / sizeof(GattCharacteristic *));
+ 
+// Software
+static char         swversion[31] = "Sensor build (0001)";
+GattCharacteristic  swChars(GattCharacteristic::UUID_SOFTWARE_REVISION_STRING_CHAR, (uint8_t *)swversion, sizeof(swversion), sizeof(swversion),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *softwareChars[] = {&swChars };
+GattService         softwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, softwareChars, sizeof(softwareChars) / sizeof(GattCharacteristic *));
+// Hardware
+static char         hwversion[31] = "Sensor hw proto 0";
+GattCharacteristic  hwChars(GattCharacteristic::UUID_HARDWARE_REVISION_STRING_CHAR, (uint8_t *)hwversion, sizeof(hwversion), sizeof(hwversion),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *hardwareChars[] = {&hwChars };
+GattService         hardwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, hardwareChars, sizeof(hardwareChars) / sizeof(GattCharacteristic *));
+// Manufacturer
+static char         vendor[31] = "Busybee.io";
+GattCharacteristic  vendorChars(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR, (uint8_t *)vendor, sizeof(vendor), sizeof(vendor),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *manufacturerChars[] = {&vendorChars };
+GattService         manufacturerService(GattService::UUID_DEVICE_INFORMATION_SERVICE, manufacturerChars, sizeof(manufacturerChars) / sizeof(GattCharacteristic *));
+// Serial number
+static char         serial[31] = "1234567890";
+GattCharacteristic  serialChars(GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR, (uint8_t *)serial, sizeof(serial), sizeof(serial),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *serialNumberChars[] = {&serialChars };
+GattService         serialNumberService(GattService::UUID_DEVICE_INFORMATION_SERVICE, serialNumberChars, sizeof(serialNumberChars) / sizeof(GattCharacteristic *));
+ 
+static uint8_t      batteryLevel = 100;
+GattCharacteristic  batteryPercentage(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, (uint8_t *)batteryLevel, sizeof(batteryLevel), sizeof(batteryLevel),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+GattCharacteristic *batteryChars[] = {&batteryPercentage };
+GattService         batteryService(GattService::UUID_BATTERY_SERVICE, batteryChars, sizeof(batteryChars) / sizeof(GattCharacteristic *));
+
+
+/* CSC Service */
 /* Service:  https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.cycling_speed_and_cadence.xml*/
 /* CSC Mes: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.csc_measurement.xml */
 /* Feature: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.csc_feature.xml */
 /* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.sensor_location.xml */
 /* Control point: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.sc_control_point.xml */
-static uint16_t cscCumulativeWheelRevolutions = 0;
+static uint8_t cscWheelRevolutionDataSPresent = 1;
+static uint8_t cscCrankRevolutionDataSPresent = 1;
+static uint32_t cscCumulativeWheelRevolutions = 0;
 static uint16_t cscLastWheelEventTime = 0;          // Unit is second & has a resolution of 1/1024s. 
 static uint16_t cscCumulativeCrankRevolutions = 0;
 static uint16_t cscLastCrankEventTime = 0;          // Unit is second & has a resolution of 1/1024s.
+static uint8_t csc_mes_flags = (cscCrankRevolutionDataSPresent << 1) + cscWheelRevolutionDataSPresent;
+static uint8_t csc_mes[] = {csc_mes_flags, cscCumulativeWheelRevolutions & 0x000000FF, cscCumulativeWheelRevolutions & 0x0000FF00, cscCumulativeWheelRevolutions & 0x00FF0000, cscCumulativeWheelRevolutions & 0xFF000000, cscLastWheelEventTime & 0x00FF, cscLastWheelEventTime & 0xFF00, cscCumulativeCrankRevolutions & 0x00FF, cscCumulativeCrankRevolutions & 0xFF00, cscLastCrankEventTime & 0x00FF, cscLastCrankEventTime & 0xFF00 };
+//static uint8_t csc_mes[5] = { (cscCrankRevolutionDataSPresent << 1) + cscWheelRevolutionDataSPresent, cscCumulativeWheelRevolutions & 0x000000FF, cscLastWheelEventTime & 0x00FF, cscCumulativeCrankRevolutions & 0x00FF, cscLastCrankEventTime & 0x00FF };
+
+GattCharacteristic cscMeasurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, csc_mes, sizeof(csc_mes), sizeof(csc_mes),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
 
 static bool cscWheelRevolutionDataSupported = true;
 static bool cscWCrankRevolutionDataSupported = true;
-static bool cscMultipleSensorLocationsSupported = true;
+static bool cscMultipleSensorLocationsSupported = false;
+static uint8_t csc_feat_flags = (cscWheelRevolutionDataSupported << 2) + (cscWCrankRevolutionDataSupported << 1) + cscMultipleSensorLocationsSupported;
+static uint8_t csc_feat[2] = { 0x00, csc_feat_flags };
+GattCharacteristic cscFeature(GattCharacteristic::UUID_CSC_FEATURE_CHAR, csc_feat, sizeof(csc_feat), sizeof(csc_feat),
+                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
 
-static uint8_t csc_mes[4] = {cscCumulativeWheelRevolutions, cscLastWheelEventTime, cscCumulativeCrankRevolutions, cscLastCrankEventTime};
-static uint8_t csc_feat[3] = {cscWheelRevolutionDataSupported, cscWCrankRevolutionDataSupported, cscMultipleSensorLocationsSupported};
-GattCharacteristic cscMeasurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, csc_mes, sizeof(csc_mes), sizeof(csc_mes),
-                           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
 static const uint8_t location = 0x09; /* Front Hub */
-GattCharacteristic cscMesLocation(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR,
+GattCharacteristic cscLocation(GattCharacteristic::UUID_SENSOR_LOCATION,
                                (uint8_t *)&location, sizeof(location), sizeof(location),
                                GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
-GattCharacteristic *cscChars[] = {&cscMeasurement, &cscMesLocation, };
+
+/* TODO: implement a Write charac. cf. wheelSizeCallback()
+GattCharacteristic cscCtrlPoint(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR,
+                               (uint8_t *)&location, sizeof(location), sizeof(location),
+                               GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
+*/
+GattCharacteristic *cscChars[] = {&cscMeasurement, &cscFeature,  };     //&cscLocation, &cscControlPoint,
 GattService        cscService(GattService::UUID_CYCLING_SPEED_AND_CADENCE, cscChars, sizeof(cscChars) / sizeof(GattCharacteristic *));
 
-static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
+static const uint16_t uuid16_list[] = {GattService::UUID_CYCLING_SPEED_AND_CADENCE};
+
+void wheelSizeCallback() {
+    DEBUG("Wheel size request ack!");
+    return;
+}
+    
 
 void disconnectionCallback(void)
 {
@@ -68,22 +152,29 @@
 }
 
 /**
- * Triggered periodically by the 'ticker' interrupt; updates hrmCounter.
+ * Triggered periodically by the 'ticker' interrupt; updates cycling stats & battery value.
  */
 void periodicCallback(void)
 {
     led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
 
     if (ble.getGapState().connected) {
-        /* Update the HRM measurement */
-        /* 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 */
+        DEBUG("Ble connected!");
+        led1 = 1;
+        
+        /* Update the CSC measurement */
         cscCumulativeWheelRevolutions+=3;
-        cscCumulativeCrankRevolutions++;
+        cscCumulativeCrankRevolutions+=2;
+        cscLastWheelEventTime++;
+        cscLastCrankEventTime++;
 
-        csc_mes[1] = cscCumulativeWheelRevolutions;
-        csc_mes[3] = cscCumulativeCrankRevolutions;
-        ble.updateCharacteristicValue(cscMeasurement.getHandle(), csc_mes, sizeof(csc_mes));
+        // Update the battery level
+        batteryLevel--;
+        ble.updateCharacteristicValue(batteryPercentage.getHandle(), &batteryLevel, sizeof(batteryLevel));
+
+        uint8_t new_csc_mes[] = {csc_mes_flags, cscCumulativeWheelRevolutions & 0x000000FF, cscCumulativeWheelRevolutions & 0x0000FF00, cscCumulativeWheelRevolutions & 0x00FF0000, cscCumulativeWheelRevolutions & 0xFF000000, cscLastWheelEventTime & 0x00FF, cscLastWheelEventTime & 0xFF00, cscCumulativeCrankRevolutions & 0x00FF, cscCumulativeCrankRevolutions & 0xFF00, cscLastCrankEventTime & 0x00FF, cscLastCrankEventTime & 0xFF00 };
+        
+        ble.updateCharacteristicValue(cscMeasurement.getHandle(), new_csc_mes, sizeof(new_csc_mes));
     }
 }
 
@@ -93,20 +184,32 @@
     Ticker ticker;
     ticker.attach(periodicCallback, 1);
 
-    DEBUG("Initialising the nRF51822\n\r");
+    DEBUG("Initialized the nRF51822\n\r");
     ble.init();
     ble.onDisconnection(disconnectionCallback);
+    ble.onDataSent(wheelSizeCallback);
 
     /* setup advertising */
-    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //
     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
-    ble.accumulateAdvertisingPayload(GapAdvertisingData::CYCLING_SPEED_AND_CADENCE_SENSOR);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_CYCLING);
     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
     ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
     ble.startAdvertising();
+    
+    /* Setup services */
+    ble.addService(cscService);
+    /*ble.addService(batteryService);
+    //ble.addService(firmwareService);
+    ble.addService(manufacturerService);
+    ble.addService(modelService);
+    ble.addService(temperatureService);
+*/
+    DEBUG("Initialized the BLE stack\n\r");
 
-    ble.addService(cscService);
+DEBUG("feat val = %d - mes val = %d", csc_feat_flags, csc_mes_flags);
+DEBUG("\r\n");
 
     while (true) {
         ble.waitForEvent();