HTM Demo of BLE with Microbit

Dependencies:   microbit

Committer:
dw02136
Date:
Sat Aug 10 07:46:21 2019 +0000
Revision:
2:7c86dc4b74a8
Parent:
1:7623f55dd990
use Display

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dw02136 0:d44120452d31 1 /*
dw02136 0:d44120452d31 2 The MIT License (MIT)
dw02136 0:d44120452d31 3
dw02136 0:d44120452d31 4 Copyright (c) 2016 British Broadcasting Corporation.
dw02136 0:d44120452d31 5 This software is provided by Lancaster University by arrangement with the BBC.
dw02136 0:d44120452d31 6
dw02136 0:d44120452d31 7 Permission is hereby granted, free of charge, to any person obtaining a
dw02136 0:d44120452d31 8 copy of this software and associated documentation files (the "Software"),
dw02136 0:d44120452d31 9 to deal in the Software without restriction, including without limitation
dw02136 0:d44120452d31 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
dw02136 0:d44120452d31 11 and/or sell copies of the Software, and to permit persons to whom the
dw02136 0:d44120452d31 12 Software is furnished to do so, subject to the following conditions:
dw02136 0:d44120452d31 13
dw02136 0:d44120452d31 14 The above copyright notice and this permission notice shall be included in
dw02136 0:d44120452d31 15 all copies or substantial portions of the Software.
dw02136 0:d44120452d31 16
dw02136 0:d44120452d31 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
dw02136 0:d44120452d31 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
dw02136 0:d44120452d31 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
dw02136 0:d44120452d31 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
dw02136 0:d44120452d31 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
dw02136 0:d44120452d31 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
dw02136 0:d44120452d31 23 DEALINGS IN THE SOFTWARE.
dw02136 0:d44120452d31 24 */
dw02136 0:d44120452d31 25
dw02136 0:d44120452d31 26 #include "MicroBit.h"
dw02136 0:d44120452d31 27
dw02136 0:d44120452d31 28 const static char DEVICE_NAME[] = "MY_MICROBIT";
dw02136 0:d44120452d31 29 static volatile bool triggerSensorPolling = false;
dw02136 0:d44120452d31 30
dw02136 0:d44120452d31 31 MicroBit uBit;
dw02136 0:d44120452d31 32 Ticker ticker;
dw02136 0:d44120452d31 33 Serial pc(USBTX, USBRX);
dw02136 0:d44120452d31 34
dw02136 2:7c86dc4b74a8 35 bool isConnect = false;
dw02136 2:7c86dc4b74a8 36
dw02136 1:7623f55dd990 37 /* Health Thermometer Service */
dw02136 1:7623f55dd990 38 float temperature = 25.0;
dw02136 1:7623f55dd990 39 uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 };
dw02136 1:7623f55dd990 40
dw02136 1:7623f55dd990 41 GattCharacteristic tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
dw02136 1:7623f55dd990 42 thermTempPayload, 5, 5,
dw02136 1:7623f55dd990 43 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
dw02136 0:d44120452d31 44
dw02136 0:d44120452d31 45 /* Battery Level Service */
dw02136 0:d44120452d31 46 uint8_t batt = 100; /* Battery level */
dw02136 0:d44120452d31 47 GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR,
dw02136 0:d44120452d31 48 (uint8_t *)batt, 1, 1,
dw02136 1:7623f55dd990 49 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
dw02136 1:7623f55dd990 50
dw02136 1:7623f55dd990 51 GattCharacteristic *htmChars[] = {&tempChar, };
dw02136 0:d44120452d31 52 GattCharacteristic *battChars[] = {&battLevel, };
dw02136 1:7623f55dd990 53
dw02136 1:7623f55dd990 54 GattService htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars,
dw02136 1:7623f55dd990 55 sizeof(htmChars) / sizeof(GattCharacteristic *));
dw02136 0:d44120452d31 56 GattService battService(GattService::UUID_BATTERY_SERVICE, battChars,
dw02136 0:d44120452d31 57 sizeof(battChars) / sizeof(GattCharacteristic *));
dw02136 1:7623f55dd990 58 uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
dw02136 1:7623f55dd990 59 GattService::UUID_BATTERY_SERVICE};
dw02136 1:7623f55dd990 60
dw02136 1:7623f55dd990 61 static Gap::ConnectionParams_t connectionParams;
dw02136 1:7623f55dd990 62
dw02136 1:7623f55dd990 63 uint32_t quick_ieee11073_from_float(float temperature);
dw02136 2:7c86dc4b74a8 64 void updateServiceValues(void);
dw02136 0:d44120452d31 65
dw02136 0:d44120452d31 66 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
dw02136 0:d44120452d31 67 {
dw02136 2:7c86dc4b74a8 68 isConnect = true;
dw02136 0:d44120452d31 69 pc.printf("connected. Got handle %u\r\n", params->handle);
dw02136 0:d44120452d31 70
dw02136 0:d44120452d31 71 connectionParams.slaveLatency = 1;
dw02136 0:d44120452d31 72 if (uBit.ble->gap().updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) {
dw02136 0:d44120452d31 73 pc.printf("failed to update connection paramter\r\n");
dw02136 0:d44120452d31 74 }
dw02136 0:d44120452d31 75 }
dw02136 0:d44120452d31 76
dw02136 0:d44120452d31 77 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
dw02136 0:d44120452d31 78 {
dw02136 2:7c86dc4b74a8 79 isConnect = false;
dw02136 0:d44120452d31 80 pc.printf("Disconnected handle %u, reason %u\r\n", params->handle, params->reason);
dw02136 0:d44120452d31 81 pc.printf("Restarting the advertising process\r\n");
dw02136 0:d44120452d31 82
dw02136 2:7c86dc4b74a8 83 pc.printf("Start Advertising\r\n");
dw02136 0:d44120452d31 84 uBit.ble->gap().startAdvertising();
dw02136 0:d44120452d31 85 }
dw02136 0:d44120452d31 86
dw02136 0:d44120452d31 87 void periodicCallback(void)
dw02136 0:d44120452d31 88 {
dw02136 0:d44120452d31 89 triggerSensorPolling = true;
dw02136 0:d44120452d31 90 }
dw02136 0:d44120452d31 91
dw02136 0:d44120452d31 92 int main()
dw02136 0:d44120452d31 93 {
dw02136 0:d44120452d31 94 // Initialise the micro:bit runtime.
dw02136 0:d44120452d31 95 pc.printf("Initialising MicroBit\r\n");
dw02136 0:d44120452d31 96 uBit.ble = new BLEDevice();
dw02136 0:d44120452d31 97 uBit.init();
dw02136 0:d44120452d31 98 uBit.ble->init();
dw02136 0:d44120452d31 99 pc.printf("Init done\r\n");
dw02136 0:d44120452d31 100
dw02136 0:d44120452d31 101 uBit.ble->gap().onConnection(onConnectionCallback);
dw02136 0:d44120452d31 102 uBit.ble->gap().onDisconnection(disconnectionCallback);
dw02136 0:d44120452d31 103
dw02136 0:d44120452d31 104 /* setup advertising */
dw02136 0:d44120452d31 105 uBit.ble->gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
dw02136 0:d44120452d31 106 uBit.ble->gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
dw02136 1:7623f55dd990 107 uBit.ble->gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
dw02136 0:d44120452d31 108 uBit.ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
dw02136 0:d44120452d31 109 uBit.ble->gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
dw02136 0:d44120452d31 110 uBit.ble->setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
dw02136 0:d44120452d31 111 uBit.ble->startAdvertising();
dw02136 0:d44120452d31 112 pc.printf("Start Advertising\r\n");
dw02136 0:d44120452d31 113
dw02136 1:7623f55dd990 114 uBit.ble->gattServer().addService(htmService);
dw02136 0:d44120452d31 115 uBit.ble->gattServer().addService(battService);
dw02136 1:7623f55dd990 116 pc.printf("Add Service\r\n");
dw02136 2:7c86dc4b74a8 117
dw02136 0:d44120452d31 118 ticker.attach(periodicCallback, 1);
dw02136 0:d44120452d31 119
dw02136 0:d44120452d31 120 // Insert your code here!
dw02136 0:d44120452d31 121 while(1)
dw02136 0:d44120452d31 122 {
dw02136 2:7c86dc4b74a8 123 if(isConnect)
dw02136 2:7c86dc4b74a8 124 {
dw02136 2:7c86dc4b74a8 125 uBit.display.printChar('C');
dw02136 2:7c86dc4b74a8 126 }
dw02136 2:7c86dc4b74a8 127 else
dw02136 2:7c86dc4b74a8 128 {
dw02136 2:7c86dc4b74a8 129 uBit.display.printChar('A');
dw02136 2:7c86dc4b74a8 130 }
dw02136 2:7c86dc4b74a8 131
dw02136 0:d44120452d31 132 //uBit.display.scroll("ADV");
dw02136 0:d44120452d31 133 if (triggerSensorPolling) {
dw02136 0:d44120452d31 134 triggerSensorPolling = false;
dw02136 2:7c86dc4b74a8 135 updateServiceValues();
dw02136 0:d44120452d31 136 } else {
dw02136 0:d44120452d31 137 uBit.ble->waitForEvent();
dw02136 0:d44120452d31 138 }
dw02136 0:d44120452d31 139 }
dw02136 0:d44120452d31 140
dw02136 0:d44120452d31 141 // If main exits, there may still be other fibers running or registered event handlers etc.
dw02136 0:d44120452d31 142 // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
dw02136 0:d44120452d31 143 // sit in the idle task forever, in a power efficient sleep.
dw02136 0:d44120452d31 144 //release_fiber();
dw02136 0:d44120452d31 145 }
dw02136 0:d44120452d31 146
dw02136 2:7c86dc4b74a8 147 /**************************************************************************/
dw02136 2:7c86dc4b74a8 148 /*!
dw02136 2:7c86dc4b74a8 149 @brief Ticker callback to switch advertisingStateLed state
dw02136 2:7c86dc4b74a8 150 */
dw02136 2:7c86dc4b74a8 151 /**************************************************************************/
dw02136 2:7c86dc4b74a8 152 void updateServiceValues(void)
dw02136 2:7c86dc4b74a8 153 {
dw02136 2:7c86dc4b74a8 154 // Decrement the battery level.
dw02136 2:7c86dc4b74a8 155 batt <=50 ? batt=100 : batt--;
dw02136 2:7c86dc4b74a8 156 pc.printf("Batt is %u\r\n", batt);
dw02136 2:7c86dc4b74a8 157
dw02136 2:7c86dc4b74a8 158 /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
dw02136 2:7c86dc4b74a8 159 temperature >= 30.0 ? temperature = 20.0 : temperature+=0.2;
dw02136 2:7c86dc4b74a8 160 pc.printf("temp:%f\r\n", temperature);
dw02136 2:7c86dc4b74a8 161 uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
dw02136 2:7c86dc4b74a8 162 memcpy(thermTempPayload+1, &temp_ieee11073, 4);
dw02136 2:7c86dc4b74a8 163 uBit.ble->gattServer().write(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload)); //Mod
dw02136 2:7c86dc4b74a8 164 uBit.ble->gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt)); //Mod
dw02136 2:7c86dc4b74a8 165 }
dw02136 2:7c86dc4b74a8 166
dw02136 1:7623f55dd990 167 /**
dw02136 1:7623f55dd990 168 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
dw02136 1:7623f55dd990 169 * @param temperature The temperature as a float.
dw02136 1:7623f55dd990 170 * @return The temperature in 11073-20601 FLOAT-Type format.
dw02136 1:7623f55dd990 171 */
dw02136 1:7623f55dd990 172 uint32_t quick_ieee11073_from_float(float temperature)
dw02136 1:7623f55dd990 173 {
dw02136 1:7623f55dd990 174 uint8_t exponent = 0xFF; //exponent is -1
dw02136 1:7623f55dd990 175 uint32_t mantissa = (uint32_t)(temperature*10);
dw02136 1:7623f55dd990 176
dw02136 1:7623f55dd990 177 return ( ((uint32_t)exponent) << 24) | mantissa;
dw02136 1:7623f55dd990 178 }