Firmware for Keewi v1 electronic board
Dependencies: BLE_API mbed nRF51822
Fork of Keewi_v1 by
main.cpp@3:6e08445f54f3, 2014-08-20 (annotated)
- Committer:
- clemberto
- Date:
- Wed Aug 20 08:59:22 2014 +0000
- Revision:
- 3:6e08445f54f3
- Parent:
- 2:8ebada2e4924
Bluetooth service (CSC, NUS, LBS) - simulated data
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
clemberto | 0:4f6fbeb69f11 | 1 | /* mbed Microcontroller Library |
clemberto | 0:4f6fbeb69f11 | 2 | * Copyright (c) 2006-2013 ARM Limited |
clemberto | 0:4f6fbeb69f11 | 3 | * |
clemberto | 0:4f6fbeb69f11 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
clemberto | 0:4f6fbeb69f11 | 5 | * you may not use this file except in compliance with the License. |
clemberto | 0:4f6fbeb69f11 | 6 | * You may obtain a copy of the License at |
clemberto | 0:4f6fbeb69f11 | 7 | * |
clemberto | 0:4f6fbeb69f11 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
clemberto | 0:4f6fbeb69f11 | 9 | * |
clemberto | 0:4f6fbeb69f11 | 10 | * Unless required by applicable law or agreed to in writing, software |
clemberto | 0:4f6fbeb69f11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
clemberto | 0:4f6fbeb69f11 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
clemberto | 0:4f6fbeb69f11 | 13 | * See the License for the specific language governing permissions and |
clemberto | 0:4f6fbeb69f11 | 14 | * limitations under the License. |
clemberto | 0:4f6fbeb69f11 | 15 | */ |
clemberto | 0:4f6fbeb69f11 | 16 | |
clemberto | 0:4f6fbeb69f11 | 17 | #include "mbed.h" |
clemberto | 0:4f6fbeb69f11 | 18 | #include "BLEDevice.h" |
clemberto | 0:4f6fbeb69f11 | 19 | |
clemberto | 0:4f6fbeb69f11 | 20 | BLEDevice ble; |
clemberto | 0:4f6fbeb69f11 | 21 | DigitalOut led1(LED1); |
clemberto | 0:4f6fbeb69f11 | 22 | |
clemberto | 1:e60b7762dd79 | 23 | #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; |
clemberto | 0:4f6fbeb69f11 | 24 | * it will have an impact on code-size and power consumption. */ |
clemberto | 0:4f6fbeb69f11 | 25 | |
clemberto | 0:4f6fbeb69f11 | 26 | #if NEED_CONSOLE_OUTPUT |
clemberto | 0:4f6fbeb69f11 | 27 | Serial pc(USBTX, USBRX); |
clemberto | 1:e60b7762dd79 | 28 | |
clemberto | 0:4f6fbeb69f11 | 29 | #define DEBUG(...) { pc.printf(__VA_ARGS__); } |
clemberto | 0:4f6fbeb69f11 | 30 | #else |
clemberto | 0:4f6fbeb69f11 | 31 | #define DEBUG(...) /* nothing */ |
clemberto | 0:4f6fbeb69f11 | 32 | #endif /* #if NEED_CONSOLE_OUTPUT */ |
clemberto | 0:4f6fbeb69f11 | 33 | |
clemberto | 1:e60b7762dd79 | 34 | const static char DEVICE_NAME[] = "Keewi v1"; |
clemberto | 0:4f6fbeb69f11 | 35 | |
clemberto | 1:e60b7762dd79 | 36 | // DEVICE_NAME_UUID = '2A00'; // Nordic fixed this to nRF5, can be written |
clemberto | 1:e60b7762dd79 | 37 | |
clemberto | 1:e60b7762dd79 | 38 | // Temperature 0-100 C, simulated |
clemberto | 1:e60b7762dd79 | 39 | static uint8_t temperature = 32; |
clemberto | 1:e60b7762dd79 | 40 | GattCharacteristic tempMeas(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, (uint8_t *)temperature, sizeof(temperature), sizeof(temperature), |
clemberto | 1:e60b7762dd79 | 41 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
clemberto | 1:e60b7762dd79 | 42 | GattCharacteristic *temperatureChars[] = {&tempMeas }; |
clemberto | 1:e60b7762dd79 | 43 | // TODO: config service Health thermo |
clemberto | 1:e60b7762dd79 | 44 | GattService temperatureService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, temperatureChars, sizeof(temperatureChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 45 | |
clemberto | 1:e60b7762dd79 | 46 | // SYSTEM |
clemberto | 1:e60b7762dd79 | 47 | static char systemId = 'A'; |
clemberto | 1:e60b7762dd79 | 48 | GattCharacteristic systemID(GattCharacteristic::UUID_SYSTEM_ID_CHAR, (uint8_t *)systemId, sizeof(systemId), sizeof(systemId), |
clemberto | 1:e60b7762dd79 | 49 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 50 | GattCharacteristic *systemChars[] = {&systemID }; |
clemberto | 1:e60b7762dd79 | 51 | GattService systemService(GattService::UUID_DEVICE_INFORMATION_SERVICE, systemChars, sizeof(systemChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 52 | |
clemberto | 1:e60b7762dd79 | 53 | // MODEL |
clemberto | 1:e60b7762dd79 | 54 | static char model[31] = "mBed nRF51822"; |
clemberto | 1:e60b7762dd79 | 55 | GattCharacteristic modelID(GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR, (uint8_t *)model, sizeof(model), sizeof(model), |
clemberto | 1:e60b7762dd79 | 56 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 57 | GattCharacteristic *modelChars[] = {&modelID }; |
clemberto | 1:e60b7762dd79 | 58 | GattService modelService(GattService::UUID_DEVICE_INFORMATION_SERVICE, modelChars, sizeof(modelChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 59 | |
clemberto | 1:e60b7762dd79 | 60 | // Firmware |
clemberto | 1:e60b7762dd79 | 61 | static char fwversion[31] = "Firmware: 0216"; |
clemberto | 1:e60b7762dd79 | 62 | GattCharacteristic fwChars(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR, (uint8_t *)fwversion, sizeof(fwversion), sizeof(fwversion), |
clemberto | 1:e60b7762dd79 | 63 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 64 | GattCharacteristic *firmwareChars[] = {&fwChars }; |
clemberto | 1:e60b7762dd79 | 65 | GattService firmwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, firmwareChars, sizeof(firmwareChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 66 | |
clemberto | 1:e60b7762dd79 | 67 | // Software |
clemberto | 1:e60b7762dd79 | 68 | static char swversion[31] = "Sensor build (0001)"; |
clemberto | 1:e60b7762dd79 | 69 | GattCharacteristic swChars(GattCharacteristic::UUID_SOFTWARE_REVISION_STRING_CHAR, (uint8_t *)swversion, sizeof(swversion), sizeof(swversion), |
clemberto | 1:e60b7762dd79 | 70 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 71 | GattCharacteristic *softwareChars[] = {&swChars }; |
clemberto | 1:e60b7762dd79 | 72 | GattService softwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, softwareChars, sizeof(softwareChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 73 | // Hardware |
clemberto | 1:e60b7762dd79 | 74 | static char hwversion[31] = "Sensor hw proto 0"; |
clemberto | 1:e60b7762dd79 | 75 | GattCharacteristic hwChars(GattCharacteristic::UUID_HARDWARE_REVISION_STRING_CHAR, (uint8_t *)hwversion, sizeof(hwversion), sizeof(hwversion), |
clemberto | 1:e60b7762dd79 | 76 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 77 | GattCharacteristic *hardwareChars[] = {&hwChars }; |
clemberto | 1:e60b7762dd79 | 78 | GattService hardwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, hardwareChars, sizeof(hardwareChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 79 | // Manufacturer |
clemberto | 1:e60b7762dd79 | 80 | static char vendor[31] = "Busybee.io"; |
clemberto | 1:e60b7762dd79 | 81 | GattCharacteristic vendorChars(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR, (uint8_t *)vendor, sizeof(vendor), sizeof(vendor), |
clemberto | 1:e60b7762dd79 | 82 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 83 | GattCharacteristic *manufacturerChars[] = {&vendorChars }; |
clemberto | 1:e60b7762dd79 | 84 | GattService manufacturerService(GattService::UUID_DEVICE_INFORMATION_SERVICE, manufacturerChars, sizeof(manufacturerChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 85 | // Serial number |
clemberto | 1:e60b7762dd79 | 86 | static char serial[31] = "1234567890"; |
clemberto | 1:e60b7762dd79 | 87 | GattCharacteristic serialChars(GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR, (uint8_t *)serial, sizeof(serial), sizeof(serial), |
clemberto | 1:e60b7762dd79 | 88 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 1:e60b7762dd79 | 89 | GattCharacteristic *serialNumberChars[] = {&serialChars }; |
clemberto | 1:e60b7762dd79 | 90 | GattService serialNumberService(GattService::UUID_DEVICE_INFORMATION_SERVICE, serialNumberChars, sizeof(serialNumberChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 91 | |
clemberto | 1:e60b7762dd79 | 92 | static uint8_t batteryLevel = 100; |
clemberto | 1:e60b7762dd79 | 93 | GattCharacteristic batteryPercentage(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, (uint8_t *)batteryLevel, sizeof(batteryLevel), sizeof(batteryLevel), |
clemberto | 1:e60b7762dd79 | 94 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
clemberto | 1:e60b7762dd79 | 95 | GattCharacteristic *batteryChars[] = {&batteryPercentage }; |
clemberto | 1:e60b7762dd79 | 96 | GattService batteryService(GattService::UUID_BATTERY_SERVICE, batteryChars, sizeof(batteryChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 97 | |
clemberto | 1:e60b7762dd79 | 98 | |
clemberto | 1:e60b7762dd79 | 99 | /* CSC Service */ |
clemberto | 0:4f6fbeb69f11 | 100 | /* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.cycling_speed_and_cadence.xml*/ |
clemberto | 0:4f6fbeb69f11 | 101 | /* CSC Mes: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.csc_measurement.xml */ |
clemberto | 0:4f6fbeb69f11 | 102 | /* Feature: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.csc_feature.xml */ |
clemberto | 0:4f6fbeb69f11 | 103 | /* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.sensor_location.xml */ |
clemberto | 0:4f6fbeb69f11 | 104 | /* Control point: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.sc_control_point.xml */ |
clemberto | 1:e60b7762dd79 | 105 | static uint8_t cscWheelRevolutionDataSPresent = 1; |
clemberto | 1:e60b7762dd79 | 106 | static uint8_t cscCrankRevolutionDataSPresent = 1; |
clemberto | 1:e60b7762dd79 | 107 | static uint32_t cscCumulativeWheelRevolutions = 0; |
clemberto | 0:4f6fbeb69f11 | 108 | static uint16_t cscLastWheelEventTime = 0; // Unit is second & has a resolution of 1/1024s. |
clemberto | 0:4f6fbeb69f11 | 109 | static uint16_t cscCumulativeCrankRevolutions = 0; |
clemberto | 0:4f6fbeb69f11 | 110 | static uint16_t cscLastCrankEventTime = 0; // Unit is second & has a resolution of 1/1024s. |
clemberto | 1:e60b7762dd79 | 111 | static uint8_t csc_mes_flags = (cscCrankRevolutionDataSPresent << 1) + cscWheelRevolutionDataSPresent; |
clemberto | 2:8ebada2e4924 | 112 | static uint8_t csc_mes[] = { csc_mes_flags, |
clemberto | 2:8ebada2e4924 | 113 | cscCumulativeWheelRevolutions & 0x000000FF , |
clemberto | 2:8ebada2e4924 | 114 | cscCumulativeWheelRevolutions & 0x0000FF00 , |
clemberto | 2:8ebada2e4924 | 115 | cscCumulativeWheelRevolutions & 0x00FF0000 , |
clemberto | 2:8ebada2e4924 | 116 | cscCumulativeWheelRevolutions & 0xFF000000 , |
clemberto | 2:8ebada2e4924 | 117 | cscLastWheelEventTime & 0x00FF , |
clemberto | 2:8ebada2e4924 | 118 | cscLastWheelEventTime & 0xFF00 , |
clemberto | 2:8ebada2e4924 | 119 | cscCumulativeCrankRevolutions & 0x00FF , |
clemberto | 2:8ebada2e4924 | 120 | cscCumulativeCrankRevolutions & 0xFF00 , |
clemberto | 2:8ebada2e4924 | 121 | cscLastCrankEventTime & 0x00FF , |
clemberto | 2:8ebada2e4924 | 122 | cscLastCrankEventTime & 0xFF00 }; |
clemberto | 1:e60b7762dd79 | 123 | GattCharacteristic cscMeasurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, csc_mes, sizeof(csc_mes), sizeof(csc_mes), |
clemberto | 1:e60b7762dd79 | 124 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
clemberto | 0:4f6fbeb69f11 | 125 | static bool cscWheelRevolutionDataSupported = true; |
clemberto | 0:4f6fbeb69f11 | 126 | static bool cscWCrankRevolutionDataSupported = true; |
clemberto | 1:e60b7762dd79 | 127 | static bool cscMultipleSensorLocationsSupported = false; |
clemberto | 1:e60b7762dd79 | 128 | static uint8_t csc_feat_flags = (cscWheelRevolutionDataSupported << 2) + (cscWCrankRevolutionDataSupported << 1) + cscMultipleSensorLocationsSupported; |
clemberto | 1:e60b7762dd79 | 129 | static uint8_t csc_feat[2] = { 0x00, csc_feat_flags }; |
clemberto | 1:e60b7762dd79 | 130 | GattCharacteristic cscFeature(GattCharacteristic::UUID_CSC_FEATURE_CHAR, csc_feat, sizeof(csc_feat), sizeof(csc_feat), |
clemberto | 1:e60b7762dd79 | 131 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 2:8ebada2e4924 | 132 | /* Sensor location */ |
clemberto | 2:8ebada2e4924 | 133 | enum BLE_SENSOR_LOCATION_LIST { /**< possible location for the CSC sensor. */ |
clemberto | 2:8ebada2e4924 | 134 | BLE_SENSOR_LOCATION_OTHER , |
clemberto | 2:8ebada2e4924 | 135 | BLE_SENSOR_LOCATION_TOP_OF_SHOE , |
clemberto | 2:8ebada2e4924 | 136 | BLE_SENSOR_LOCATION_IN_SHOE , |
clemberto | 2:8ebada2e4924 | 137 | BLE_SENSOR_LOCATION_HIP , |
clemberto | 2:8ebada2e4924 | 138 | BLE_SENSOR_LOCATION_FRONT_WHEEL , |
clemberto | 2:8ebada2e4924 | 139 | BLE_SENSOR_LOCATION_LEFT_CRANK , |
clemberto | 2:8ebada2e4924 | 140 | BLE_SENSOR_LOCATION_RIGHT_CRANK , |
clemberto | 2:8ebada2e4924 | 141 | BLE_SENSOR_LOCATION_LEFT_PEDAL , |
clemberto | 2:8ebada2e4924 | 142 | BLE_SENSOR_LOCATION_RIGHT_PEDAL , |
clemberto | 2:8ebada2e4924 | 143 | BLE_SENSOR_LOCATION_FRONT_HUB , |
clemberto | 2:8ebada2e4924 | 144 | BLE_SENSOR_LOCATION_REAR_DROPOUT, |
clemberto | 2:8ebada2e4924 | 145 | BLE_SENSOR_LOCATION_CHAINSTAY , |
clemberto | 2:8ebada2e4924 | 146 | BLE_SENSOR_LOCATION_REAR_WHEEL , |
clemberto | 2:8ebada2e4924 | 147 | BLE_SENSOR_LOCATION_REAR_HUB , |
clemberto | 2:8ebada2e4924 | 148 | BLE_SENSOR_LOCATION_CHEST |
clemberto | 2:8ebada2e4924 | 149 | }; |
clemberto | 2:8ebada2e4924 | 150 | static uint8_t keewi_v1_location_possibilities[] = { /**< possible location for Keewi. */ |
clemberto | 2:8ebada2e4924 | 151 | BLE_SENSOR_LOCATION_OTHER , |
clemberto | 2:8ebada2e4924 | 152 | BLE_SENSOR_LOCATION_FRONT_WHEEL , |
clemberto | 2:8ebada2e4924 | 153 | BLE_SENSOR_LOCATION_LEFT_CRANK , |
clemberto | 2:8ebada2e4924 | 154 | BLE_SENSOR_LOCATION_RIGHT_CRANK , |
clemberto | 2:8ebada2e4924 | 155 | BLE_SENSOR_LOCATION_FRONT_HUB , |
clemberto | 2:8ebada2e4924 | 156 | BLE_SENSOR_LOCATION_REAR_WHEEL , |
clemberto | 2:8ebada2e4924 | 157 | BLE_SENSOR_LOCATION_REAR_HUB |
clemberto | 2:8ebada2e4924 | 158 | }; |
clemberto | 2:8ebada2e4924 | 159 | static const uint8_t location = BLE_SENSOR_LOCATION_FRONT_WHEEL; // Keewi v1 speed sensor default location |
clemberto | 1:e60b7762dd79 | 160 | GattCharacteristic cscLocation(GattCharacteristic::UUID_SENSOR_LOCATION, |
clemberto | 0:4f6fbeb69f11 | 161 | (uint8_t *)&location, sizeof(location), sizeof(location), |
clemberto | 0:4f6fbeb69f11 | 162 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 2:8ebada2e4924 | 163 | |
clemberto | 2:8ebada2e4924 | 164 | // SC Control Point |
clemberto | 2:8ebada2e4924 | 165 | //TODO: implement a Write charac. cf. paramUpdateCallback() |
clemberto | 1:e60b7762dd79 | 166 | GattCharacteristic cscCtrlPoint(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, |
clemberto | 1:e60b7762dd79 | 167 | (uint8_t *)&location, sizeof(location), sizeof(location), |
clemberto | 1:e60b7762dd79 | 168 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE); |
clemberto | 2:8ebada2e4924 | 169 | GattCharacteristic *cscChars[] = {&cscMeasurement, &cscFeature, &cscLocation, }; // &cscControlPoint, |
clemberto | 0:4f6fbeb69f11 | 170 | GattService cscService(GattService::UUID_CYCLING_SPEED_AND_CADENCE, cscChars, sizeof(cscChars) / sizeof(GattCharacteristic *)); |
clemberto | 0:4f6fbeb69f11 | 171 | |
clemberto | 3:6e08445f54f3 | 172 | /* Led & button service (LBS) |
clemberto | 2:8ebada2e4924 | 173 | Switch: Front & rear lights |
clemberto | 3:6e08445f54f3 | 174 | Led: Alarm state |
clemberto | 2:8ebada2e4924 | 175 | */ |
clemberto | 2:8ebada2e4924 | 176 | #define LBS_UUID_BASE {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00} |
clemberto | 2:8ebada2e4924 | 177 | #define LBS_UUID_LED_CHAR 0x1525 |
clemberto | 2:8ebada2e4924 | 178 | #define LBS_UUID_BUTTON_CHAR 0x1524 |
clemberto | 2:8ebada2e4924 | 179 | static bool rLightState = true; |
clemberto | 2:8ebada2e4924 | 180 | static bool fLightState = true; |
clemberto | 3:6e08445f54f3 | 181 | static uint8_t lbs_butt_flags = fLightState + (rLightState << 1); |
clemberto | 3:6e08445f54f3 | 182 | GattCharacteristic lbsButtons(LBS_UUID_BUTTON_CHAR, |
clemberto | 3:6e08445f54f3 | 183 | (uint8_t *)&lbs_butt_flags, sizeof(lbs_butt_flags), sizeof(lbs_butt_flags), |
clemberto | 2:8ebada2e4924 | 184 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE); |
clemberto | 3:6e08445f54f3 | 185 | static bool alarmState = false; |
clemberto | 3:6e08445f54f3 | 186 | static uint8_t lbs_led_flags = alarmState; |
clemberto | 3:6e08445f54f3 | 187 | GattCharacteristic lbsLeds(LBS_UUID_LED_CHAR, |
clemberto | 3:6e08445f54f3 | 188 | (uint8_t *)&lbs_led_flags, sizeof(lbs_led_flags), sizeof(lbs_led_flags), |
clemberto | 2:8ebada2e4924 | 189 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
clemberto | 3:6e08445f54f3 | 190 | GattCharacteristic *lbsChars[] = {&lbsButtons, &lbsLeds, }; |
clemberto | 2:8ebada2e4924 | 191 | #define LBS_UUID_SERVICE 0x1523 |
clemberto | 2:8ebada2e4924 | 192 | GattService lbsService(LBS_UUID_SERVICE, lbsChars, sizeof(lbsChars) / sizeof(GattCharacteristic *)); |
clemberto | 1:e60b7762dd79 | 193 | |
clemberto | 3:6e08445f54f3 | 194 | /* Nordic UART Service (nus) |
clemberto | 3:6e08445f54f3 | 195 | TX: sending ride data |
clemberto | 3:6e08445f54f3 | 196 | RX: receiving ack, unlocking alarm |
clemberto | 2:8ebada2e4924 | 197 | */ |
clemberto | 2:8ebada2e4924 | 198 | #define BLE_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */ |
clemberto | 2:8ebada2e4924 | 199 | #define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0002 /**< The UUID of the TX Characteristic. */ |
clemberto | 2:8ebada2e4924 | 200 | #define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0003 /**< The UUID of the RX Characteristic. */ |
clemberto | 2:8ebada2e4924 | 201 | #define BLE_NUS_MAX_DATA_LEN (GATT_MTU_SIZE_DEFAULT - 3) /**< Maximum length of data (in bytes) that can be transmitted by the Nordic UART service module to the peer. */ |
clemberto | 2:8ebada2e4924 | 202 | #define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ |
clemberto | 3:6e08445f54f3 | 203 | #define BLE_NUS_MAX_TX_CHAR_LEN 9 /**< Maximum length of the TX Characteristic (in bytes). */ |
clemberto | 3:6e08445f54f3 | 204 | static const uint8_t uart_base_uuid[] = {0x6e, 0x40, 0x00, 0x01, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5,0x0e, 0x24, 0xdc, 0xca, 0x9e}; |
clemberto | 3:6e08445f54f3 | 205 | static const uint8_t uart_tx_uuid[] = {0x6e, 0x40, 0x00, 0x02, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5,0x0e, 0x24, 0xdc, 0xca, 0x9e}; |
clemberto | 3:6e08445f54f3 | 206 | static const uint8_t uart_rx_uuid[] = {0x6e, 0x40, 0x00, 0x03, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5,0x0e, 0x24, 0xdc, 0xca, 0x9e}; |
clemberto | 3:6e08445f54f3 | 207 | static const uint8_t uart_base_uuid_rev[] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e}; |
clemberto | 3:6e08445f54f3 | 208 | uint8_t nus_rx_buffer[BLE_NUS_MAX_RX_CHAR_LEN] = {0,}; |
clemberto | 3:6e08445f54f3 | 209 | GattCharacteristic nusRx(uart_rx_uuid, |
clemberto | 3:6e08445f54f3 | 210 | (uint8_t *)&nus_rx_buffer, sizeof(nus_rx_buffer), BLE_NUS_MAX_RX_CHAR_LEN, |
clemberto | 3:6e08445f54f3 | 211 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
clemberto | 3:6e08445f54f3 | 212 | uint8_t nus_tx_buffer[BLE_NUS_MAX_TX_CHAR_LEN] = {0,}; |
clemberto | 3:6e08445f54f3 | 213 | GattCharacteristic nusTx(uart_tx_uuid, |
clemberto | 3:6e08445f54f3 | 214 | (uint8_t *)&nus_tx_buffer, sizeof(nus_tx_buffer), BLE_NUS_MAX_TX_CHAR_LEN, |
clemberto | 3:6e08445f54f3 | 215 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); |
clemberto | 3:6e08445f54f3 | 216 | GattCharacteristic *nusChars[] = {&nusTx, &nusRx, }; |
clemberto | 3:6e08445f54f3 | 217 | GattService nusService(uart_base_uuid, nusChars, sizeof(nusChars) / sizeof(GattCharacteristic *)); |
clemberto | 2:8ebada2e4924 | 218 | |
clemberto | 2:8ebada2e4924 | 219 | /* List of all available services */ |
clemberto | 2:8ebada2e4924 | 220 | static const uint16_t uuid16_list[] = { |
clemberto | 2:8ebada2e4924 | 221 | GattService::UUID_CYCLING_SPEED_AND_CADENCE, |
clemberto | 2:8ebada2e4924 | 222 | GattService::UUID_BATTERY_SERVICE, |
clemberto | 2:8ebada2e4924 | 223 | GattService::UUID_CURRENT_TIME_SERVICE, |
clemberto | 2:8ebada2e4924 | 224 | LBS_UUID_SERVICE, |
clemberto | 3:6e08445f54f3 | 225 | BLE_UUID_NUS_SERVICE, |
clemberto | 2:8ebada2e4924 | 226 | }; |
clemberto | 2:8ebada2e4924 | 227 | |
clemberto | 2:8ebada2e4924 | 228 | |
clemberto | 2:8ebada2e4924 | 229 | void paramUpdateCallback() { |
clemberto | 2:8ebada2e4924 | 230 | DEBUG("Param change request ack!"); |
clemberto | 1:e60b7762dd79 | 231 | return; |
clemberto | 1:e60b7762dd79 | 232 | } |
clemberto | 2:8ebada2e4924 | 233 | |
clemberto | 0:4f6fbeb69f11 | 234 | |
clemberto | 0:4f6fbeb69f11 | 235 | void disconnectionCallback(void) |
clemberto | 0:4f6fbeb69f11 | 236 | { |
clemberto | 0:4f6fbeb69f11 | 237 | DEBUG("Disconnected!\n\r"); |
clemberto | 0:4f6fbeb69f11 | 238 | DEBUG("Restarting the advertising process\n\r"); |
clemberto | 0:4f6fbeb69f11 | 239 | ble.startAdvertising(); |
clemberto | 0:4f6fbeb69f11 | 240 | } |
clemberto | 0:4f6fbeb69f11 | 241 | |
clemberto | 0:4f6fbeb69f11 | 242 | /** |
clemberto | 1:e60b7762dd79 | 243 | * Triggered periodically by the 'ticker' interrupt; updates cycling stats & battery value. |
clemberto | 0:4f6fbeb69f11 | 244 | */ |
clemberto | 0:4f6fbeb69f11 | 245 | void periodicCallback(void) |
clemberto | 0:4f6fbeb69f11 | 246 | { |
clemberto | 0:4f6fbeb69f11 | 247 | led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ |
clemberto | 0:4f6fbeb69f11 | 248 | |
clemberto | 0:4f6fbeb69f11 | 249 | if (ble.getGapState().connected) { |
clemberto | 1:e60b7762dd79 | 250 | led1 = 1; |
clemberto | 1:e60b7762dd79 | 251 | |
clemberto | 2:8ebada2e4924 | 252 | // Simulate evolution of battery level |
clemberto | 1:e60b7762dd79 | 253 | batteryLevel--; |
clemberto | 1:e60b7762dd79 | 254 | ble.updateCharacteristicValue(batteryPercentage.getHandle(), &batteryLevel, sizeof(batteryLevel)); |
clemberto | 1:e60b7762dd79 | 255 | |
clemberto | 2:8ebada2e4924 | 256 | // Simulate evolution of Speed & Cadence |
clemberto | 2:8ebada2e4924 | 257 | cscCumulativeWheelRevolutions+=5; |
clemberto | 2:8ebada2e4924 | 258 | cscCumulativeCrankRevolutions+=2; |
clemberto | 2:8ebada2e4924 | 259 | cscLastWheelEventTime+=1000; |
clemberto | 2:8ebada2e4924 | 260 | cscLastCrankEventTime+=1000; |
clemberto | 1:e60b7762dd79 | 261 | 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 }; |
clemberto | 2:8ebada2e4924 | 262 | ble.updateCharacteristicValue(cscMeasurement.getHandle(), new_csc_mes, sizeof(new_csc_mes)); |
clemberto | 1:e60b7762dd79 | 263 | |
clemberto | 2:8ebada2e4924 | 264 | // Notify alarm & lights status |
clemberto | 3:6e08445f54f3 | 265 | alarmState ^= 1; |
clemberto | 3:6e08445f54f3 | 266 | uint8_t new_lbs_butt_flags = (uint8_t)alarmState; |
clemberto | 3:6e08445f54f3 | 267 | ble.updateCharacteristicValue(lbsLeds.getHandle(), &new_lbs_butt_flags, sizeof(new_lbs_butt_flags)); |
clemberto | 2:8ebada2e4924 | 268 | |
clemberto | 3:6e08445f54f3 | 269 | DEBUG("led val = %d\r\n", new_lbs_butt_flags); |
clemberto | 2:8ebada2e4924 | 270 | |
clemberto | 0:4f6fbeb69f11 | 271 | } |
clemberto | 0:4f6fbeb69f11 | 272 | } |
clemberto | 0:4f6fbeb69f11 | 273 | |
clemberto | 0:4f6fbeb69f11 | 274 | int main(void) |
clemberto | 0:4f6fbeb69f11 | 275 | { |
clemberto | 0:4f6fbeb69f11 | 276 | led1 = 1; |
clemberto | 0:4f6fbeb69f11 | 277 | Ticker ticker; |
clemberto | 0:4f6fbeb69f11 | 278 | ticker.attach(periodicCallback, 1); |
clemberto | 0:4f6fbeb69f11 | 279 | |
clemberto | 1:e60b7762dd79 | 280 | DEBUG("Initialized the nRF51822\n\r"); |
clemberto | 0:4f6fbeb69f11 | 281 | ble.init(); |
clemberto | 0:4f6fbeb69f11 | 282 | ble.onDisconnection(disconnectionCallback); |
clemberto | 2:8ebada2e4924 | 283 | ble.onDataSent(paramUpdateCallback); |
clemberto | 0:4f6fbeb69f11 | 284 | |
clemberto | 0:4f6fbeb69f11 | 285 | /* setup advertising */ |
clemberto | 1:e60b7762dd79 | 286 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // |
clemberto | 3:6e08445f54f3 | 287 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, |
clemberto | 3:6e08445f54f3 | 288 | (uint8_t*)uuid16_list, sizeof(uuid16_list)); |
clemberto | 3:6e08445f54f3 | 289 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
clemberto | 3:6e08445f54f3 | 290 | (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid)); |
clemberto | 1:e60b7762dd79 | 291 | ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_CYCLING); |
clemberto | 0:4f6fbeb69f11 | 292 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
clemberto | 0:4f6fbeb69f11 | 293 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
clemberto | 0:4f6fbeb69f11 | 294 | ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ |
clemberto | 0:4f6fbeb69f11 | 295 | ble.startAdvertising(); |
clemberto | 1:e60b7762dd79 | 296 | |
clemberto | 1:e60b7762dd79 | 297 | /* Setup services */ |
clemberto | 1:e60b7762dd79 | 298 | ble.addService(cscService); |
clemberto | 2:8ebada2e4924 | 299 | ble.addService(batteryService); |
clemberto | 1:e60b7762dd79 | 300 | //ble.addService(firmwareService); |
clemberto | 1:e60b7762dd79 | 301 | ble.addService(manufacturerService); |
clemberto | 2:8ebada2e4924 | 302 | ble.addService(lbsService); |
clemberto | 3:6e08445f54f3 | 303 | ble.addService(nusService); |
clemberto | 2:8ebada2e4924 | 304 | |
clemberto | 1:e60b7762dd79 | 305 | DEBUG("Initialized the BLE stack\n\r"); |
clemberto | 0:4f6fbeb69f11 | 306 | |
clemberto | 0:4f6fbeb69f11 | 307 | while (true) { |
clemberto | 0:4f6fbeb69f11 | 308 | ble.waitForEvent(); |
clemberto | 0:4f6fbeb69f11 | 309 | } |
clemberto | 0:4f6fbeb69f11 | 310 | } |