BLE demo for the Cycling Speed and Cadence service.
Dependencies: BLE_API mbed nRF51822
Diff: main.cpp
- Revision:
- 0:ea0fa3076efd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Mar 10 13:09:47 2016 +0000 @@ -0,0 +1,129 @@ +/* +Copyright (c) 2016 Y. Miyakawa + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "mbed.h" +#include "ble/BLE.h" +#include "CyclingSpeedAndCadenceService.h" +#include "ble/services/DeviceInformationService.h" + +DigitalOut led1(LED1); + +const static char DEVICE_NAME[] = "CSC1"; +static const uint16_t uuid16_list[] = {GattService::UUID_CYCLING_SPEED_AND_CADENCE, + GattService::UUID_DEVICE_INFORMATION_SERVICE}; + +static volatile bool triggerSensorPolling = false; + +CyclingSpeedAndCadenceService *cyclingSpeedAndCadenceService; +DeviceInformationService *deviceInfo; + +uint16_t feature = CyclingSpeedAndCadenceService::FEATURE_WHEEL_REVOLUTION_DATA + + CyclingSpeedAndCadenceService::FEATURE_CRANK_REVOLUTION_DATA; + +uint8_t flags = CyclingSpeedAndCadenceService::FLAG_WHEEL_REVOLUTION_DATA_PRESENT + + CyclingSpeedAndCadenceService::FLAG_CRANK_REVOLUTION_DATA_PRESENT; + +uint8_t location = CyclingSpeedAndCadenceService::LOCATION_CHAINSTAY; + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) +{ +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) +{ + triggerSensorPolling = false; + BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); // restart advertising +} + +void confirmationRcvCallBack(Gap::Handle_t handle) +{ +} + +void periodicCallback(void) +{ + led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ + + /* Note that the periodicCallback() executes in interrupt context, so it is safer to do + * heavy-weight sensor polling from the main thread. */ + triggerSensorPolling = true; +} + +void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) +{ + BLE &ble = params->ble; + ble_error_t error = params->error; + + if (error != BLE_ERROR_NONE) { + return; + } + + ble.gap().onConnection(connectionCallback); + ble.gap().onDisconnection(disconnectionCallback); + ble.onConfirmationReceived(confirmationRcvCallBack); + + /* Setup primary service. */ + cyclingSpeedAndCadenceService = new CyclingSpeedAndCadenceService(ble, feature, location); + + /* Setup auxiliary service. */ + deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); + + /* Setup advertising. */ + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); + ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.gap().setAdvertisingInterval(1000); /* 1000ms */ + ble.gap().startAdvertising(); +} + +int main(void) +{ + uint16_t dCumulativeWheelRev = 4; + uint16_t dLastWheelEventTime = 1024; + uint16_t dCumulativeCrankRev = 1; + uint16_t dLastCrankEventTime = 1024; + + led1 = 1; + + Ticker ticker; + ticker.attach(periodicCallback, 1); // blink LED every second + + BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE); + ble.init(bleInitComplete); + + /* SpinWait for initialization to complete. This is necessary because the + * BLE object is used in the main loop below. */ + while (ble.hasInitialized() == false) { /* spin loop */ } + + // infinite loop + while(1) { + if (triggerSensorPolling && ble.getGapState().connected) { + triggerSensorPolling = false; + dLastWheelEventTime -= 32; + dLastCrankEventTime -= 32; + if (dLastWheelEventTime < 512) { + dLastWheelEventTime = 1024; + dLastCrankEventTime = 1024; + } + cyclingSpeedAndCadenceService->updateCyclingSpeedAndCadence(flags, + dCumulativeWheelRev, dLastWheelEventTime, dCumulativeCrankRev, dLastCrankEventTime); + } else { + ble.waitForEvent(); // low power wait for event + } + } +}