BLE demo for the Cycling Speed and Cadence service.
Dependencies: BLE_API mbed nRF51822
main.cpp@0:ea0fa3076efd, 2016-03-10 (annotated)
- Committer:
- p3miya
- Date:
- Thu Mar 10 13:09:47 2016 +0000
- Revision:
- 0:ea0fa3076efd
BLE demo for the Cycling Speed and Cadence service.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
p3miya | 0:ea0fa3076efd | 1 | /* |
p3miya | 0:ea0fa3076efd | 2 | Copyright (c) 2016 Y. Miyakawa |
p3miya | 0:ea0fa3076efd | 3 | |
p3miya | 0:ea0fa3076efd | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
p3miya | 0:ea0fa3076efd | 5 | and associated documentation files (the "Software"), to deal in the Software without restriction, |
p3miya | 0:ea0fa3076efd | 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, |
p3miya | 0:ea0fa3076efd | 7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, |
p3miya | 0:ea0fa3076efd | 8 | subject to the following conditions: |
p3miya | 0:ea0fa3076efd | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
p3miya | 0:ea0fa3076efd | 10 | |
p3miya | 0:ea0fa3076efd | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
p3miya | 0:ea0fa3076efd | 12 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
p3miya | 0:ea0fa3076efd | 13 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
p3miya | 0:ea0fa3076efd | 14 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
p3miya | 0:ea0fa3076efd | 15 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
p3miya | 0:ea0fa3076efd | 16 | */ |
p3miya | 0:ea0fa3076efd | 17 | |
p3miya | 0:ea0fa3076efd | 18 | #include "mbed.h" |
p3miya | 0:ea0fa3076efd | 19 | #include "ble/BLE.h" |
p3miya | 0:ea0fa3076efd | 20 | #include "CyclingSpeedAndCadenceService.h" |
p3miya | 0:ea0fa3076efd | 21 | #include "ble/services/DeviceInformationService.h" |
p3miya | 0:ea0fa3076efd | 22 | |
p3miya | 0:ea0fa3076efd | 23 | DigitalOut led1(LED1); |
p3miya | 0:ea0fa3076efd | 24 | |
p3miya | 0:ea0fa3076efd | 25 | const static char DEVICE_NAME[] = "CSC1"; |
p3miya | 0:ea0fa3076efd | 26 | static const uint16_t uuid16_list[] = {GattService::UUID_CYCLING_SPEED_AND_CADENCE, |
p3miya | 0:ea0fa3076efd | 27 | GattService::UUID_DEVICE_INFORMATION_SERVICE}; |
p3miya | 0:ea0fa3076efd | 28 | |
p3miya | 0:ea0fa3076efd | 29 | static volatile bool triggerSensorPolling = false; |
p3miya | 0:ea0fa3076efd | 30 | |
p3miya | 0:ea0fa3076efd | 31 | CyclingSpeedAndCadenceService *cyclingSpeedAndCadenceService; |
p3miya | 0:ea0fa3076efd | 32 | DeviceInformationService *deviceInfo; |
p3miya | 0:ea0fa3076efd | 33 | |
p3miya | 0:ea0fa3076efd | 34 | uint16_t feature = CyclingSpeedAndCadenceService::FEATURE_WHEEL_REVOLUTION_DATA |
p3miya | 0:ea0fa3076efd | 35 | + CyclingSpeedAndCadenceService::FEATURE_CRANK_REVOLUTION_DATA; |
p3miya | 0:ea0fa3076efd | 36 | |
p3miya | 0:ea0fa3076efd | 37 | uint8_t flags = CyclingSpeedAndCadenceService::FLAG_WHEEL_REVOLUTION_DATA_PRESENT |
p3miya | 0:ea0fa3076efd | 38 | + CyclingSpeedAndCadenceService::FLAG_CRANK_REVOLUTION_DATA_PRESENT; |
p3miya | 0:ea0fa3076efd | 39 | |
p3miya | 0:ea0fa3076efd | 40 | uint8_t location = CyclingSpeedAndCadenceService::LOCATION_CHAINSTAY; |
p3miya | 0:ea0fa3076efd | 41 | |
p3miya | 0:ea0fa3076efd | 42 | void connectionCallback(const Gap::ConnectionCallbackParams_t *params) |
p3miya | 0:ea0fa3076efd | 43 | { |
p3miya | 0:ea0fa3076efd | 44 | } |
p3miya | 0:ea0fa3076efd | 45 | |
p3miya | 0:ea0fa3076efd | 46 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
p3miya | 0:ea0fa3076efd | 47 | { |
p3miya | 0:ea0fa3076efd | 48 | triggerSensorPolling = false; |
p3miya | 0:ea0fa3076efd | 49 | BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); // restart advertising |
p3miya | 0:ea0fa3076efd | 50 | } |
p3miya | 0:ea0fa3076efd | 51 | |
p3miya | 0:ea0fa3076efd | 52 | void confirmationRcvCallBack(Gap::Handle_t handle) |
p3miya | 0:ea0fa3076efd | 53 | { |
p3miya | 0:ea0fa3076efd | 54 | } |
p3miya | 0:ea0fa3076efd | 55 | |
p3miya | 0:ea0fa3076efd | 56 | void periodicCallback(void) |
p3miya | 0:ea0fa3076efd | 57 | { |
p3miya | 0:ea0fa3076efd | 58 | led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ |
p3miya | 0:ea0fa3076efd | 59 | |
p3miya | 0:ea0fa3076efd | 60 | /* Note that the periodicCallback() executes in interrupt context, so it is safer to do |
p3miya | 0:ea0fa3076efd | 61 | * heavy-weight sensor polling from the main thread. */ |
p3miya | 0:ea0fa3076efd | 62 | triggerSensorPolling = true; |
p3miya | 0:ea0fa3076efd | 63 | } |
p3miya | 0:ea0fa3076efd | 64 | |
p3miya | 0:ea0fa3076efd | 65 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
p3miya | 0:ea0fa3076efd | 66 | { |
p3miya | 0:ea0fa3076efd | 67 | BLE &ble = params->ble; |
p3miya | 0:ea0fa3076efd | 68 | ble_error_t error = params->error; |
p3miya | 0:ea0fa3076efd | 69 | |
p3miya | 0:ea0fa3076efd | 70 | if (error != BLE_ERROR_NONE) { |
p3miya | 0:ea0fa3076efd | 71 | return; |
p3miya | 0:ea0fa3076efd | 72 | } |
p3miya | 0:ea0fa3076efd | 73 | |
p3miya | 0:ea0fa3076efd | 74 | ble.gap().onConnection(connectionCallback); |
p3miya | 0:ea0fa3076efd | 75 | ble.gap().onDisconnection(disconnectionCallback); |
p3miya | 0:ea0fa3076efd | 76 | ble.onConfirmationReceived(confirmationRcvCallBack); |
p3miya | 0:ea0fa3076efd | 77 | |
p3miya | 0:ea0fa3076efd | 78 | /* Setup primary service. */ |
p3miya | 0:ea0fa3076efd | 79 | cyclingSpeedAndCadenceService = new CyclingSpeedAndCadenceService(ble, feature, location); |
p3miya | 0:ea0fa3076efd | 80 | |
p3miya | 0:ea0fa3076efd | 81 | /* Setup auxiliary service. */ |
p3miya | 0:ea0fa3076efd | 82 | deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); |
p3miya | 0:ea0fa3076efd | 83 | |
p3miya | 0:ea0fa3076efd | 84 | /* Setup advertising. */ |
p3miya | 0:ea0fa3076efd | 85 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
p3miya | 0:ea0fa3076efd | 86 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
p3miya | 0:ea0fa3076efd | 87 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); |
p3miya | 0:ea0fa3076efd | 88 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
p3miya | 0:ea0fa3076efd | 89 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
p3miya | 0:ea0fa3076efd | 90 | ble.gap().setAdvertisingInterval(1000); /* 1000ms */ |
p3miya | 0:ea0fa3076efd | 91 | ble.gap().startAdvertising(); |
p3miya | 0:ea0fa3076efd | 92 | } |
p3miya | 0:ea0fa3076efd | 93 | |
p3miya | 0:ea0fa3076efd | 94 | int main(void) |
p3miya | 0:ea0fa3076efd | 95 | { |
p3miya | 0:ea0fa3076efd | 96 | uint16_t dCumulativeWheelRev = 4; |
p3miya | 0:ea0fa3076efd | 97 | uint16_t dLastWheelEventTime = 1024; |
p3miya | 0:ea0fa3076efd | 98 | uint16_t dCumulativeCrankRev = 1; |
p3miya | 0:ea0fa3076efd | 99 | uint16_t dLastCrankEventTime = 1024; |
p3miya | 0:ea0fa3076efd | 100 | |
p3miya | 0:ea0fa3076efd | 101 | led1 = 1; |
p3miya | 0:ea0fa3076efd | 102 | |
p3miya | 0:ea0fa3076efd | 103 | Ticker ticker; |
p3miya | 0:ea0fa3076efd | 104 | ticker.attach(periodicCallback, 1); // blink LED every second |
p3miya | 0:ea0fa3076efd | 105 | |
p3miya | 0:ea0fa3076efd | 106 | BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE); |
p3miya | 0:ea0fa3076efd | 107 | ble.init(bleInitComplete); |
p3miya | 0:ea0fa3076efd | 108 | |
p3miya | 0:ea0fa3076efd | 109 | /* SpinWait for initialization to complete. This is necessary because the |
p3miya | 0:ea0fa3076efd | 110 | * BLE object is used in the main loop below. */ |
p3miya | 0:ea0fa3076efd | 111 | while (ble.hasInitialized() == false) { /* spin loop */ } |
p3miya | 0:ea0fa3076efd | 112 | |
p3miya | 0:ea0fa3076efd | 113 | // infinite loop |
p3miya | 0:ea0fa3076efd | 114 | while(1) { |
p3miya | 0:ea0fa3076efd | 115 | if (triggerSensorPolling && ble.getGapState().connected) { |
p3miya | 0:ea0fa3076efd | 116 | triggerSensorPolling = false; |
p3miya | 0:ea0fa3076efd | 117 | dLastWheelEventTime -= 32; |
p3miya | 0:ea0fa3076efd | 118 | dLastCrankEventTime -= 32; |
p3miya | 0:ea0fa3076efd | 119 | if (dLastWheelEventTime < 512) { |
p3miya | 0:ea0fa3076efd | 120 | dLastWheelEventTime = 1024; |
p3miya | 0:ea0fa3076efd | 121 | dLastCrankEventTime = 1024; |
p3miya | 0:ea0fa3076efd | 122 | } |
p3miya | 0:ea0fa3076efd | 123 | cyclingSpeedAndCadenceService->updateCyclingSpeedAndCadence(flags, |
p3miya | 0:ea0fa3076efd | 124 | dCumulativeWheelRev, dLastWheelEventTime, dCumulativeCrankRev, dLastCrankEventTime); |
p3miya | 0:ea0fa3076efd | 125 | } else { |
p3miya | 0:ea0fa3076efd | 126 | ble.waitForEvent(); // low power wait for event |
p3miya | 0:ea0fa3076efd | 127 | } |
p3miya | 0:ea0fa3076efd | 128 | } |
p3miya | 0:ea0fa3076efd | 129 | } |