Official Sheffield ARMBand micro:bit program

Committer:
MrBedfordVan
Date:
Mon Oct 17 12:41:20 2016 +0000
Revision:
0:b9164b348919
Official Sheffield ARMBand Micro:bit program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MrBedfordVan 0:b9164b348919 1 /*
MrBedfordVan 0:b9164b348919 2 The MIT License (MIT)
MrBedfordVan 0:b9164b348919 3
MrBedfordVan 0:b9164b348919 4 Copyright (c) 2016 British Broadcasting Corporation.
MrBedfordVan 0:b9164b348919 5 This software is provided by Lancaster University by arrangement with the BBC.
MrBedfordVan 0:b9164b348919 6
MrBedfordVan 0:b9164b348919 7 Permission is hereby granted, free of charge, to any person obtaining a
MrBedfordVan 0:b9164b348919 8 copy of this software and associated documentation files (the "Software"),
MrBedfordVan 0:b9164b348919 9 to deal in the Software without restriction, including without limitation
MrBedfordVan 0:b9164b348919 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
MrBedfordVan 0:b9164b348919 11 and/or sell copies of the Software, and to permit persons to whom the
MrBedfordVan 0:b9164b348919 12 Software is furnished to do so, subject to the following conditions:
MrBedfordVan 0:b9164b348919 13
MrBedfordVan 0:b9164b348919 14 The above copyright notice and this permission notice shall be included in
MrBedfordVan 0:b9164b348919 15 all copies or substantial portions of the Software.
MrBedfordVan 0:b9164b348919 16
MrBedfordVan 0:b9164b348919 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
MrBedfordVan 0:b9164b348919 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
MrBedfordVan 0:b9164b348919 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
MrBedfordVan 0:b9164b348919 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
MrBedfordVan 0:b9164b348919 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
MrBedfordVan 0:b9164b348919 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
MrBedfordVan 0:b9164b348919 23 DEALINGS IN THE SOFTWARE.
MrBedfordVan 0:b9164b348919 24 */
MrBedfordVan 0:b9164b348919 25
MrBedfordVan 0:b9164b348919 26 #include "MicroBitConfig.h"
MrBedfordVan 0:b9164b348919 27 #include "MicroBitBLEManager.h"
MrBedfordVan 0:b9164b348919 28 #include "MicroBitStorage.h"
MrBedfordVan 0:b9164b348919 29 #include "MicroBitFiber.h"
MrBedfordVan 0:b9164b348919 30
MrBedfordVan 0:b9164b348919 31
MrBedfordVan 0:b9164b348919 32 /* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ.
MrBedfordVan 0:b9164b348919 33 * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
MrBedfordVan 0:b9164b348919 34 * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
MrBedfordVan 0:b9164b348919 35 * as a compatability option, but does not support the options used...
MrBedfordVan 0:b9164b348919 36 */
MrBedfordVan 0:b9164b348919 37 #if !defined(__arm)
MrBedfordVan 0:b9164b348919 38 #pragma GCC diagnostic ignored "-Wunused-function"
MrBedfordVan 0:b9164b348919 39 #pragma GCC diagnostic push
MrBedfordVan 0:b9164b348919 40 #pragma GCC diagnostic ignored "-Wunused-parameter"
MrBedfordVan 0:b9164b348919 41 #endif
MrBedfordVan 0:b9164b348919 42
MrBedfordVan 0:b9164b348919 43 #include "ble.h"
MrBedfordVan 0:b9164b348919 44
MrBedfordVan 0:b9164b348919 45 extern "C"
MrBedfordVan 0:b9164b348919 46 {
MrBedfordVan 0:b9164b348919 47 #include "device_manager.h"
MrBedfordVan 0:b9164b348919 48 uint32_t btle_set_gatt_table_size(uint32_t size);
MrBedfordVan 0:b9164b348919 49 }
MrBedfordVan 0:b9164b348919 50
MrBedfordVan 0:b9164b348919 51 /*
MrBedfordVan 0:b9164b348919 52 * Return to our predefined compiler settings.
MrBedfordVan 0:b9164b348919 53 */
MrBedfordVan 0:b9164b348919 54 #if !defined(__arm)
MrBedfordVan 0:b9164b348919 55 #pragma GCC diagnostic pop
MrBedfordVan 0:b9164b348919 56 #endif
MrBedfordVan 0:b9164b348919 57
MrBedfordVan 0:b9164b348919 58 #define MICROBIT_PAIRING_FADE_SPEED 4
MrBedfordVan 0:b9164b348919 59
MrBedfordVan 0:b9164b348919 60 const char* MICROBIT_BLE_MANUFACTURER = NULL;
MrBedfordVan 0:b9164b348919 61 const char* MICROBIT_BLE_MODEL = "BBC micro:bit";
MrBedfordVan 0:b9164b348919 62 const char* MICROBIT_BLE_HARDWARE_VERSION = NULL;
MrBedfordVan 0:b9164b348919 63 const char* MICROBIT_BLE_FIRMWARE_VERSION = MICROBIT_DAL_VERSION;
MrBedfordVan 0:b9164b348919 64 const char* MICROBIT_BLE_SOFTWARE_VERSION = NULL;
MrBedfordVan 0:b9164b348919 65 const int8_t MICROBIT_BLE_POWER_LEVEL[] = {-30, -20, -16, -12, -8, -4, 0, 4};
MrBedfordVan 0:b9164b348919 66
MrBedfordVan 0:b9164b348919 67 /*
MrBedfordVan 0:b9164b348919 68 * Many of the mbed interfaces we need to use only support callbacks to plain C functions, rather than C++ methods.
MrBedfordVan 0:b9164b348919 69 * So, we maintain a pointer to the MicroBitBLEManager that's in use. Ths way, we can still access resources on the micro:bit
MrBedfordVan 0:b9164b348919 70 * whilst keeping the code modular.
MrBedfordVan 0:b9164b348919 71 */
MrBedfordVan 0:b9164b348919 72 static MicroBitBLEManager *manager = NULL; // Singleton reference to the BLE manager. many mbed BLE API callbacks still do not support member funcions yet. :-(
MrBedfordVan 0:b9164b348919 73 static uint8_t deviceID = 255; // Unique ID for the peer that has connected to us.
MrBedfordVan 0:b9164b348919 74 static Gap::Handle_t pairingHandle = 0; // The connection handle used during a pairing process. Used to ensure that connections are dropped elegantly.
MrBedfordVan 0:b9164b348919 75
MrBedfordVan 0:b9164b348919 76 static void storeSystemAttributes(Gap::Handle_t handle)
MrBedfordVan 0:b9164b348919 77 {
MrBedfordVan 0:b9164b348919 78 if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS)
MrBedfordVan 0:b9164b348919 79 {
MrBedfordVan 0:b9164b348919 80 ManagedString key("bleSysAttrs");
MrBedfordVan 0:b9164b348919 81
MrBedfordVan 0:b9164b348919 82 KeyValuePair* bleSysAttrs = manager->storage->get(key);
MrBedfordVan 0:b9164b348919 83
MrBedfordVan 0:b9164b348919 84 BLESysAttribute attrib;
MrBedfordVan 0:b9164b348919 85 BLESysAttributeStore attribStore;
MrBedfordVan 0:b9164b348919 86
MrBedfordVan 0:b9164b348919 87 uint16_t len = sizeof(attrib.sys_attr);
MrBedfordVan 0:b9164b348919 88
MrBedfordVan 0:b9164b348919 89 sd_ble_gatts_sys_attr_get(handle, attrib.sys_attr, &len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
MrBedfordVan 0:b9164b348919 90
MrBedfordVan 0:b9164b348919 91 //copy our stored sysAttrs
MrBedfordVan 0:b9164b348919 92 if(bleSysAttrs != NULL)
MrBedfordVan 0:b9164b348919 93 {
MrBedfordVan 0:b9164b348919 94 memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore));
MrBedfordVan 0:b9164b348919 95 delete bleSysAttrs;
MrBedfordVan 0:b9164b348919 96 }
MrBedfordVan 0:b9164b348919 97
MrBedfordVan 0:b9164b348919 98 //check if we need to update
MrBedfordVan 0:b9164b348919 99 if(memcmp(attribStore.sys_attrs[deviceID].sys_attr, attrib.sys_attr, len) != 0)
MrBedfordVan 0:b9164b348919 100 {
MrBedfordVan 0:b9164b348919 101 attribStore.sys_attrs[deviceID] = attrib;
MrBedfordVan 0:b9164b348919 102 manager->storage->put(key, (uint8_t *)&attribStore, sizeof(attribStore));
MrBedfordVan 0:b9164b348919 103 }
MrBedfordVan 0:b9164b348919 104 }
MrBedfordVan 0:b9164b348919 105 }
MrBedfordVan 0:b9164b348919 106
MrBedfordVan 0:b9164b348919 107 /**
MrBedfordVan 0:b9164b348919 108 * Callback when a BLE GATT disconnect occurs.
MrBedfordVan 0:b9164b348919 109 */
MrBedfordVan 0:b9164b348919 110 static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *reason)
MrBedfordVan 0:b9164b348919 111 {
MrBedfordVan 0:b9164b348919 112 MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_DISCONNECTED);
MrBedfordVan 0:b9164b348919 113
MrBedfordVan 0:b9164b348919 114 storeSystemAttributes(reason->handle);
MrBedfordVan 0:b9164b348919 115
MrBedfordVan 0:b9164b348919 116 if (manager)
MrBedfordVan 0:b9164b348919 117 manager->advertise();
MrBedfordVan 0:b9164b348919 118 }
MrBedfordVan 0:b9164b348919 119
MrBedfordVan 0:b9164b348919 120 /**
MrBedfordVan 0:b9164b348919 121 * Callback when a BLE connection is established.
MrBedfordVan 0:b9164b348919 122 */
MrBedfordVan 0:b9164b348919 123 static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t*)
MrBedfordVan 0:b9164b348919 124 {
MrBedfordVan 0:b9164b348919 125 MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_CONNECTED);
MrBedfordVan 0:b9164b348919 126 }
MrBedfordVan 0:b9164b348919 127
MrBedfordVan 0:b9164b348919 128 /**
MrBedfordVan 0:b9164b348919 129 * Callback when a BLE SYS_ATTR_MISSING.
MrBedfordVan 0:b9164b348919 130 */
MrBedfordVan 0:b9164b348919 131 static void bleSysAttrMissingCallback(const GattSysAttrMissingCallbackParams *params)
MrBedfordVan 0:b9164b348919 132 {
MrBedfordVan 0:b9164b348919 133 int complete = 0;
MrBedfordVan 0:b9164b348919 134 deviceID = 255;
MrBedfordVan 0:b9164b348919 135
MrBedfordVan 0:b9164b348919 136 dm_handle_t dm_handle = {0,0,0,0};
MrBedfordVan 0:b9164b348919 137
MrBedfordVan 0:b9164b348919 138 int ret = dm_handle_get(params->connHandle, &dm_handle);
MrBedfordVan 0:b9164b348919 139
MrBedfordVan 0:b9164b348919 140 if (ret == 0)
MrBedfordVan 0:b9164b348919 141 deviceID = dm_handle.device_id;
MrBedfordVan 0:b9164b348919 142
MrBedfordVan 0:b9164b348919 143 if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS)
MrBedfordVan 0:b9164b348919 144 {
MrBedfordVan 0:b9164b348919 145 ManagedString key("bleSysAttrs");
MrBedfordVan 0:b9164b348919 146
MrBedfordVan 0:b9164b348919 147 KeyValuePair* bleSysAttrs = manager->storage->get(key);
MrBedfordVan 0:b9164b348919 148
MrBedfordVan 0:b9164b348919 149 BLESysAttributeStore attribStore;
MrBedfordVan 0:b9164b348919 150 BLESysAttribute attrib;
MrBedfordVan 0:b9164b348919 151
MrBedfordVan 0:b9164b348919 152 if(bleSysAttrs != NULL)
MrBedfordVan 0:b9164b348919 153 {
MrBedfordVan 0:b9164b348919 154 //restore our sysAttrStore
MrBedfordVan 0:b9164b348919 155 memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore));
MrBedfordVan 0:b9164b348919 156 delete bleSysAttrs;
MrBedfordVan 0:b9164b348919 157
MrBedfordVan 0:b9164b348919 158 attrib = attribStore.sys_attrs[deviceID];
MrBedfordVan 0:b9164b348919 159
MrBedfordVan 0:b9164b348919 160 ret = sd_ble_gatts_sys_attr_set(params->connHandle, attrib.sys_attr, sizeof(attrib.sys_attr), BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
MrBedfordVan 0:b9164b348919 161
MrBedfordVan 0:b9164b348919 162 complete = 1;
MrBedfordVan 0:b9164b348919 163
MrBedfordVan 0:b9164b348919 164 if(ret == 0)
MrBedfordVan 0:b9164b348919 165 ret = sd_ble_gatts_service_changed(params->connHandle, 0x000c, 0xffff);
MrBedfordVan 0:b9164b348919 166 }
MrBedfordVan 0:b9164b348919 167 }
MrBedfordVan 0:b9164b348919 168
MrBedfordVan 0:b9164b348919 169 if (!complete)
MrBedfordVan 0:b9164b348919 170 sd_ble_gatts_sys_attr_set(params->connHandle, NULL, 0, 0);
MrBedfordVan 0:b9164b348919 171
MrBedfordVan 0:b9164b348919 172 }
MrBedfordVan 0:b9164b348919 173
MrBedfordVan 0:b9164b348919 174 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
MrBedfordVan 0:b9164b348919 175 {
MrBedfordVan 0:b9164b348919 176 (void) handle; /* -Wunused-param */
MrBedfordVan 0:b9164b348919 177
MrBedfordVan 0:b9164b348919 178 ManagedString passKey((const char *)passkey, SecurityManager::PASSKEY_LEN);
MrBedfordVan 0:b9164b348919 179
MrBedfordVan 0:b9164b348919 180 if (manager)
MrBedfordVan 0:b9164b348919 181 manager->pairingRequested(passKey);
MrBedfordVan 0:b9164b348919 182 }
MrBedfordVan 0:b9164b348919 183
MrBedfordVan 0:b9164b348919 184 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status)
MrBedfordVan 0:b9164b348919 185 {
MrBedfordVan 0:b9164b348919 186 (void) handle; /* -Wunused-param */
MrBedfordVan 0:b9164b348919 187
MrBedfordVan 0:b9164b348919 188 dm_handle_t dm_handle = {0,0,0,0};
MrBedfordVan 0:b9164b348919 189 int ret = dm_handle_get(handle, &dm_handle);
MrBedfordVan 0:b9164b348919 190
MrBedfordVan 0:b9164b348919 191 if (ret == 0)
MrBedfordVan 0:b9164b348919 192 deviceID = dm_handle.device_id;
MrBedfordVan 0:b9164b348919 193
MrBedfordVan 0:b9164b348919 194 if (manager)
MrBedfordVan 0:b9164b348919 195 {
MrBedfordVan 0:b9164b348919 196 pairingHandle = handle;
MrBedfordVan 0:b9164b348919 197 manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS);
MrBedfordVan 0:b9164b348919 198 }
MrBedfordVan 0:b9164b348919 199 }
MrBedfordVan 0:b9164b348919 200
MrBedfordVan 0:b9164b348919 201 /**
MrBedfordVan 0:b9164b348919 202 * Constructor.
MrBedfordVan 0:b9164b348919 203 *
MrBedfordVan 0:b9164b348919 204 * Configure and manage the micro:bit's Bluetooth Low Energy (BLE) stack.
MrBedfordVan 0:b9164b348919 205 *
MrBedfordVan 0:b9164b348919 206 * @param _storage an instance of MicroBitStorage used to persist sys attribute information. (This is required for compatability with iOS).
MrBedfordVan 0:b9164b348919 207 *
MrBedfordVan 0:b9164b348919 208 * @note The BLE stack *cannot* be brought up in a static context (the software simply hangs or corrupts itself).
MrBedfordVan 0:b9164b348919 209 * Hence, the init() member function should be used to initialise the BLE stack.
MrBedfordVan 0:b9164b348919 210 */
MrBedfordVan 0:b9164b348919 211 MicroBitBLEManager::MicroBitBLEManager(MicroBitStorage& _storage) :
MrBedfordVan 0:b9164b348919 212 storage(&_storage)
MrBedfordVan 0:b9164b348919 213 {
MrBedfordVan 0:b9164b348919 214 manager = this;
MrBedfordVan 0:b9164b348919 215 this->ble = NULL;
MrBedfordVan 0:b9164b348919 216 this->pairingStatus = 0;
MrBedfordVan 0:b9164b348919 217 }
MrBedfordVan 0:b9164b348919 218
MrBedfordVan 0:b9164b348919 219 /**
MrBedfordVan 0:b9164b348919 220 * Constructor.
MrBedfordVan 0:b9164b348919 221 *
MrBedfordVan 0:b9164b348919 222 * Configure and manage the micro:bit's Bluetooth Low Energy (BLE) stack.
MrBedfordVan 0:b9164b348919 223 *
MrBedfordVan 0:b9164b348919 224 * @note The BLE stack *cannot* be brought up in a static context (the software simply hangs or corrupts itself).
MrBedfordVan 0:b9164b348919 225 * Hence, the init() member function should be used to initialise the BLE stack.
MrBedfordVan 0:b9164b348919 226 */
MrBedfordVan 0:b9164b348919 227 MicroBitBLEManager::MicroBitBLEManager() :
MrBedfordVan 0:b9164b348919 228 storage(NULL)
MrBedfordVan 0:b9164b348919 229 {
MrBedfordVan 0:b9164b348919 230 manager = this;
MrBedfordVan 0:b9164b348919 231 this->ble = NULL;
MrBedfordVan 0:b9164b348919 232 this->pairingStatus = 0;
MrBedfordVan 0:b9164b348919 233 }
MrBedfordVan 0:b9164b348919 234
MrBedfordVan 0:b9164b348919 235 /**
MrBedfordVan 0:b9164b348919 236 * When called, the micro:bit will begin advertising for a predefined period,
MrBedfordVan 0:b9164b348919 237 * MICROBIT_BLE_ADVERTISING_TIMEOUT seconds to bonded devices.
MrBedfordVan 0:b9164b348919 238 */
MrBedfordVan 0:b9164b348919 239 void MicroBitBLEManager::advertise()
MrBedfordVan 0:b9164b348919 240 {
MrBedfordVan 0:b9164b348919 241 if(ble)
MrBedfordVan 0:b9164b348919 242 ble->gap().startAdvertising();
MrBedfordVan 0:b9164b348919 243 }
MrBedfordVan 0:b9164b348919 244
MrBedfordVan 0:b9164b348919 245 /**
MrBedfordVan 0:b9164b348919 246 * Post constructor initialisation method as the BLE stack cannot be brought
MrBedfordVan 0:b9164b348919 247 * up in a static context.
MrBedfordVan 0:b9164b348919 248 *
MrBedfordVan 0:b9164b348919 249 * @param deviceName The name used when advertising
MrBedfordVan 0:b9164b348919 250 * @param serialNumber The serial number exposed by the device information service
MrBedfordVan 0:b9164b348919 251 * @param messageBus An instance of an EventModel, used during pairing.
MrBedfordVan 0:b9164b348919 252 * @param enableBonding If true, the security manager enabled bonding.
MrBedfordVan 0:b9164b348919 253 *
MrBedfordVan 0:b9164b348919 254 * @code
MrBedfordVan 0:b9164b348919 255 * bleManager.init(uBit.getName(), uBit.getSerial(), uBit.messageBus, true);
MrBedfordVan 0:b9164b348919 256 * @endcode
MrBedfordVan 0:b9164b348919 257 */
MrBedfordVan 0:b9164b348919 258 void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber, EventModel& messageBus, bool enableBonding)
MrBedfordVan 0:b9164b348919 259 {
MrBedfordVan 0:b9164b348919 260 ManagedString BLEName("BBC micro:bit");
MrBedfordVan 0:b9164b348919 261 this->deviceName = deviceName;
MrBedfordVan 0:b9164b348919 262
MrBedfordVan 0:b9164b348919 263 #if !(CONFIG_ENABLED(MICROBIT_BLE_WHITELIST))
MrBedfordVan 0:b9164b348919 264 ManagedString namePrefix(" [");
MrBedfordVan 0:b9164b348919 265 ManagedString namePostfix("]");
MrBedfordVan 0:b9164b348919 266 BLEName = BLEName + namePrefix + deviceName + namePostfix;
MrBedfordVan 0:b9164b348919 267 #endif
MrBedfordVan 0:b9164b348919 268
MrBedfordVan 0:b9164b348919 269 // Start the BLE stack.
MrBedfordVan 0:b9164b348919 270 #if CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
MrBedfordVan 0:b9164b348919 271 btle_set_gatt_table_size(MICROBIT_SD_GATT_TABLE_SIZE);
MrBedfordVan 0:b9164b348919 272 #endif
MrBedfordVan 0:b9164b348919 273
MrBedfordVan 0:b9164b348919 274 ble = new BLEDevice();
MrBedfordVan 0:b9164b348919 275 ble->init();
MrBedfordVan 0:b9164b348919 276
MrBedfordVan 0:b9164b348919 277 // automatically restart advertising after a device disconnects.
MrBedfordVan 0:b9164b348919 278 ble->gap().onDisconnection(bleDisconnectionCallback);
MrBedfordVan 0:b9164b348919 279 ble->gattServer().onSysAttrMissing(bleSysAttrMissingCallback);
MrBedfordVan 0:b9164b348919 280
MrBedfordVan 0:b9164b348919 281 // generate an event when a Bluetooth connection is established
MrBedfordVan 0:b9164b348919 282 ble->gap().onConnection(bleConnectionCallback);
MrBedfordVan 0:b9164b348919 283
MrBedfordVan 0:b9164b348919 284 // Configure the stack to hold onto the CPU during critical timing events.
MrBedfordVan 0:b9164b348919 285 // mbed-classic performs __disable_irq() calls in its timers that can cause
MrBedfordVan 0:b9164b348919 286 // MIC failures on secure BLE channels...
MrBedfordVan 0:b9164b348919 287 ble_common_opt_radio_cpu_mutex_t opt;
MrBedfordVan 0:b9164b348919 288 opt.enable = 1;
MrBedfordVan 0:b9164b348919 289 sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);
MrBedfordVan 0:b9164b348919 290
MrBedfordVan 0:b9164b348919 291 #if CONFIG_ENABLED(MICROBIT_BLE_PRIVATE_ADDRESSES)
MrBedfordVan 0:b9164b348919 292 // Configure for private addresses, so kids' behaviour can't be easily tracked.
MrBedfordVan 0:b9164b348919 293 ble->gap().setAddress(BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, {0});
MrBedfordVan 0:b9164b348919 294 #endif
MrBedfordVan 0:b9164b348919 295
MrBedfordVan 0:b9164b348919 296 // Setup our security requirements.
MrBedfordVan 0:b9164b348919 297 ble->securityManager().onPasskeyDisplay(passkeyDisplayCallback);
MrBedfordVan 0:b9164b348919 298 ble->securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
MrBedfordVan 0:b9164b348919 299 ble->securityManager().init(enableBonding, (SecurityManager::MICROBIT_BLE_SECURITY_LEVEL == SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM), SecurityManager::IO_CAPS_DISPLAY_ONLY);
MrBedfordVan 0:b9164b348919 300
MrBedfordVan 0:b9164b348919 301 if (enableBonding)
MrBedfordVan 0:b9164b348919 302 {
MrBedfordVan 0:b9164b348919 303 // If we're in pairing mode, review the size of the bond table.
MrBedfordVan 0:b9164b348919 304 int bonds = getBondCount();
MrBedfordVan 0:b9164b348919 305
MrBedfordVan 0:b9164b348919 306 // TODO: It would be much better to implement some sort of LRU/NFU policy here,
MrBedfordVan 0:b9164b348919 307 // but this isn't currently supported in mbed, so we'd need to layer break...
MrBedfordVan 0:b9164b348919 308
MrBedfordVan 0:b9164b348919 309 // If we're full, empty the bond table.
MrBedfordVan 0:b9164b348919 310 if (bonds >= MICROBIT_BLE_MAXIMUM_BONDS)
MrBedfordVan 0:b9164b348919 311 ble->securityManager().purgeAllBondingState();
MrBedfordVan 0:b9164b348919 312 }
MrBedfordVan 0:b9164b348919 313
MrBedfordVan 0:b9164b348919 314 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)
MrBedfordVan 0:b9164b348919 315 // Configure a whitelist to filter all connection requetss from unbonded devices.
MrBedfordVan 0:b9164b348919 316 // Most BLE stacks only permit one connection at a time, so this prevents denial of service attacks.
MrBedfordVan 0:b9164b348919 317 BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS];
MrBedfordVan 0:b9164b348919 318 Gap::Whitelist_t whitelist;
MrBedfordVan 0:b9164b348919 319 whitelist.addresses = bondedAddresses;
MrBedfordVan 0:b9164b348919 320 whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS;
MrBedfordVan 0:b9164b348919 321
MrBedfordVan 0:b9164b348919 322 ble->securityManager().getAddressesFromBondTable(whitelist);
MrBedfordVan 0:b9164b348919 323
MrBedfordVan 0:b9164b348919 324 ble->gap().setWhitelist(whitelist);
MrBedfordVan 0:b9164b348919 325 ble->gap().setScanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST);
MrBedfordVan 0:b9164b348919 326 ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS);
MrBedfordVan 0:b9164b348919 327 #endif
MrBedfordVan 0:b9164b348919 328
MrBedfordVan 0:b9164b348919 329 // Configure the radio at our default power level
MrBedfordVan 0:b9164b348919 330 setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER);
MrBedfordVan 0:b9164b348919 331
MrBedfordVan 0:b9164b348919 332 // Bring up core BLE services.
MrBedfordVan 0:b9164b348919 333 #if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
MrBedfordVan 0:b9164b348919 334 new MicroBitDFUService(*ble);
MrBedfordVan 0:b9164b348919 335 #endif
MrBedfordVan 0:b9164b348919 336
MrBedfordVan 0:b9164b348919 337 #if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
MrBedfordVan 0:b9164b348919 338 DeviceInformationService ble_device_information_service (*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, serialNumber.toCharArray(), MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
MrBedfordVan 0:b9164b348919 339 #else
MrBedfordVan 0:b9164b348919 340 (void)serialNumber;
MrBedfordVan 0:b9164b348919 341 #endif
MrBedfordVan 0:b9164b348919 342
MrBedfordVan 0:b9164b348919 343 #if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE)
MrBedfordVan 0:b9164b348919 344 new MicroBitEventService(*ble, messageBus);
MrBedfordVan 0:b9164b348919 345 #else
MrBedfordVan 0:b9164b348919 346 (void)messageBus;
MrBedfordVan 0:b9164b348919 347 #endif
MrBedfordVan 0:b9164b348919 348
MrBedfordVan 0:b9164b348919 349
MrBedfordVan 0:b9164b348919 350 // Configure for high speed mode where possible.
MrBedfordVan 0:b9164b348919 351 Gap::ConnectionParams_t fast;
MrBedfordVan 0:b9164b348919 352 ble->getPreferredConnectionParams(&fast);
MrBedfordVan 0:b9164b348919 353 fast.minConnectionInterval = 8; // 10 ms
MrBedfordVan 0:b9164b348919 354 fast.maxConnectionInterval = 16; // 20 ms
MrBedfordVan 0:b9164b348919 355 fast.slaveLatency = 0;
MrBedfordVan 0:b9164b348919 356 ble->setPreferredConnectionParams(&fast);
MrBedfordVan 0:b9164b348919 357
MrBedfordVan 0:b9164b348919 358 // Setup advertising.
MrBedfordVan 0:b9164b348919 359 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)
MrBedfordVan 0:b9164b348919 360 ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
MrBedfordVan 0:b9164b348919 361 #else
MrBedfordVan 0:b9164b348919 362 ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
MrBedfordVan 0:b9164b348919 363 #endif
MrBedfordVan 0:b9164b348919 364
MrBedfordVan 0:b9164b348919 365 ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length());
MrBedfordVan 0:b9164b348919 366 ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
MrBedfordVan 0:b9164b348919 367 ble->setAdvertisingInterval(200);
MrBedfordVan 0:b9164b348919 368
MrBedfordVan 0:b9164b348919 369 #if (MICROBIT_BLE_ADVERTISING_TIMEOUT > 0)
MrBedfordVan 0:b9164b348919 370 ble->gap().setAdvertisingTimeout(MICROBIT_BLE_ADVERTISING_TIMEOUT);
MrBedfordVan 0:b9164b348919 371 #endif
MrBedfordVan 0:b9164b348919 372
MrBedfordVan 0:b9164b348919 373 // If we have whitelisting enabled, then prevent only enable advertising of we have any binded devices...
MrBedfordVan 0:b9164b348919 374 // This is to further protect kids' privacy. If no-one initiates BLE, then the device is unreachable.
MrBedfordVan 0:b9164b348919 375 // If whiltelisting is disabled, then we always advertise.
MrBedfordVan 0:b9164b348919 376 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)
MrBedfordVan 0:b9164b348919 377 if (whitelist.size > 0)
MrBedfordVan 0:b9164b348919 378 #endif
MrBedfordVan 0:b9164b348919 379 ble->startAdvertising();
MrBedfordVan 0:b9164b348919 380 }
MrBedfordVan 0:b9164b348919 381
MrBedfordVan 0:b9164b348919 382 /**
MrBedfordVan 0:b9164b348919 383 * Change the output power level of the transmitter to the given value.
MrBedfordVan 0:b9164b348919 384 *
MrBedfordVan 0:b9164b348919 385 * @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest.
MrBedfordVan 0:b9164b348919 386 *
MrBedfordVan 0:b9164b348919 387 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range.
MrBedfordVan 0:b9164b348919 388 *
MrBedfordVan 0:b9164b348919 389 * @code
MrBedfordVan 0:b9164b348919 390 * // maximum transmission power.
MrBedfordVan 0:b9164b348919 391 * bleManager.setTransmitPower(7);
MrBedfordVan 0:b9164b348919 392 * @endcode
MrBedfordVan 0:b9164b348919 393 */
MrBedfordVan 0:b9164b348919 394 int MicroBitBLEManager::setTransmitPower(int power)
MrBedfordVan 0:b9164b348919 395 {
MrBedfordVan 0:b9164b348919 396 if (power < 0 || power >= MICROBIT_BLE_POWER_LEVELS)
MrBedfordVan 0:b9164b348919 397 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 398
MrBedfordVan 0:b9164b348919 399 if (ble->gap().setTxPower(MICROBIT_BLE_POWER_LEVEL[power]) != NRF_SUCCESS)
MrBedfordVan 0:b9164b348919 400 return MICROBIT_NOT_SUPPORTED;
MrBedfordVan 0:b9164b348919 401
MrBedfordVan 0:b9164b348919 402 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 403 }
MrBedfordVan 0:b9164b348919 404
MrBedfordVan 0:b9164b348919 405 /**
MrBedfordVan 0:b9164b348919 406 * Determines the number of devices currently bonded with this micro:bit.
MrBedfordVan 0:b9164b348919 407 * @return The number of active bonds.
MrBedfordVan 0:b9164b348919 408 */
MrBedfordVan 0:b9164b348919 409 int MicroBitBLEManager::getBondCount()
MrBedfordVan 0:b9164b348919 410 {
MrBedfordVan 0:b9164b348919 411 BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS];
MrBedfordVan 0:b9164b348919 412 Gap::Whitelist_t whitelist;
MrBedfordVan 0:b9164b348919 413 whitelist.addresses = bondedAddresses;
MrBedfordVan 0:b9164b348919 414 whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS;
MrBedfordVan 0:b9164b348919 415 ble->securityManager().getAddressesFromBondTable(whitelist);
MrBedfordVan 0:b9164b348919 416
MrBedfordVan 0:b9164b348919 417 return whitelist.bonds;
MrBedfordVan 0:b9164b348919 418 }
MrBedfordVan 0:b9164b348919 419
MrBedfordVan 0:b9164b348919 420 /**
MrBedfordVan 0:b9164b348919 421 * A request to pair has been received from a BLE device.
MrBedfordVan 0:b9164b348919 422 * If we're in pairing mode, display the passkey to the user.
MrBedfordVan 0:b9164b348919 423 * Also, purge the bonding table if it has reached capacity.
MrBedfordVan 0:b9164b348919 424 *
MrBedfordVan 0:b9164b348919 425 * @note for internal use only.
MrBedfordVan 0:b9164b348919 426 */
MrBedfordVan 0:b9164b348919 427 void MicroBitBLEManager::pairingRequested(ManagedString passKey)
MrBedfordVan 0:b9164b348919 428 {
MrBedfordVan 0:b9164b348919 429 // Update our mode to display the passkey.
MrBedfordVan 0:b9164b348919 430 this->passKey = passKey;
MrBedfordVan 0:b9164b348919 431 this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST;
MrBedfordVan 0:b9164b348919 432 }
MrBedfordVan 0:b9164b348919 433
MrBedfordVan 0:b9164b348919 434 /**
MrBedfordVan 0:b9164b348919 435 * A pairing request has been sucessfully completed.
MrBedfordVan 0:b9164b348919 436 * If we're in pairing mode, display a success or failure message.
MrBedfordVan 0:b9164b348919 437 *
MrBedfordVan 0:b9164b348919 438 * @note for internal use only.
MrBedfordVan 0:b9164b348919 439 */
MrBedfordVan 0:b9164b348919 440 void MicroBitBLEManager::pairingComplete(bool success)
MrBedfordVan 0:b9164b348919 441 {
MrBedfordVan 0:b9164b348919 442 this->pairingStatus = MICROBIT_BLE_PAIR_COMPLETE;
MrBedfordVan 0:b9164b348919 443
MrBedfordVan 0:b9164b348919 444 if(success)
MrBedfordVan 0:b9164b348919 445 {
MrBedfordVan 0:b9164b348919 446 this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL;
MrBedfordVan 0:b9164b348919 447 fiber_add_idle_component(this);
MrBedfordVan 0:b9164b348919 448 }
MrBedfordVan 0:b9164b348919 449 }
MrBedfordVan 0:b9164b348919 450
MrBedfordVan 0:b9164b348919 451 /**
MrBedfordVan 0:b9164b348919 452 * Periodic callback in thread context.
MrBedfordVan 0:b9164b348919 453 * We use this here purely to safely issue a disconnect operation after a pairing operation is complete.
MrBedfordVan 0:b9164b348919 454 */
MrBedfordVan 0:b9164b348919 455 void MicroBitBLEManager::idleTick()
MrBedfordVan 0:b9164b348919 456 {
MrBedfordVan 0:b9164b348919 457 if (ble)
MrBedfordVan 0:b9164b348919 458 ble->disconnect(pairingHandle, Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF);
MrBedfordVan 0:b9164b348919 459
MrBedfordVan 0:b9164b348919 460 fiber_remove_idle_component(this);
MrBedfordVan 0:b9164b348919 461 }
MrBedfordVan 0:b9164b348919 462
MrBedfordVan 0:b9164b348919 463 /**
MrBedfordVan 0:b9164b348919 464 * Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming
MrBedfordVan 0:b9164b348919 465 * of the micro:bit in cases where BLE is disabled during normal operation.
MrBedfordVan 0:b9164b348919 466 *
MrBedfordVan 0:b9164b348919 467 * @param display An instance of MicroBitDisplay used when displaying pairing information.
MrBedfordVan 0:b9164b348919 468 * @param authorizationButton The button to use to authorise a pairing request.
MrBedfordVan 0:b9164b348919 469 *
MrBedfordVan 0:b9164b348919 470 * @code
MrBedfordVan 0:b9164b348919 471 * // initiate pairing mode
MrBedfordVan 0:b9164b348919 472 * bleManager.pairingMode(uBit.display, uBit.buttonA);
MrBedfordVan 0:b9164b348919 473 * @endcode
MrBedfordVan 0:b9164b348919 474 */
MrBedfordVan 0:b9164b348919 475 void MicroBitBLEManager::pairingMode(MicroBitDisplay& display, MicroBitButton& authorisationButton)
MrBedfordVan 0:b9164b348919 476 {
MrBedfordVan 0:b9164b348919 477 ManagedString namePrefix("BBC micro:bit [");
MrBedfordVan 0:b9164b348919 478 ManagedString namePostfix("]");
MrBedfordVan 0:b9164b348919 479 ManagedString BLEName = namePrefix + deviceName + namePostfix;
MrBedfordVan 0:b9164b348919 480
MrBedfordVan 0:b9164b348919 481 ManagedString msg("PAIRING MODE!");
MrBedfordVan 0:b9164b348919 482
MrBedfordVan 0:b9164b348919 483 int timeInPairingMode = 0;
MrBedfordVan 0:b9164b348919 484 int brightness = 255;
MrBedfordVan 0:b9164b348919 485 int fadeDirection = 0;
MrBedfordVan 0:b9164b348919 486
MrBedfordVan 0:b9164b348919 487 ble->gap().stopAdvertising();
MrBedfordVan 0:b9164b348919 488
MrBedfordVan 0:b9164b348919 489 // Clear the whitelist (if we have one), so that we're discoverable by all BLE devices.
MrBedfordVan 0:b9164b348919 490 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)
MrBedfordVan 0:b9164b348919 491 BLEProtocol::Address_t addresses[MICROBIT_BLE_MAXIMUM_BONDS];
MrBedfordVan 0:b9164b348919 492 Gap::Whitelist_t whitelist;
MrBedfordVan 0:b9164b348919 493 whitelist.addresses = addresses;
MrBedfordVan 0:b9164b348919 494 whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS;
MrBedfordVan 0:b9164b348919 495 whitelist.size = 0;
MrBedfordVan 0:b9164b348919 496 ble->gap().setWhitelist(whitelist);
MrBedfordVan 0:b9164b348919 497 ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST);
MrBedfordVan 0:b9164b348919 498 #endif
MrBedfordVan 0:b9164b348919 499
MrBedfordVan 0:b9164b348919 500 // Update the advertised name of this micro:bit to include the device name
MrBedfordVan 0:b9164b348919 501 ble->clearAdvertisingPayload();
MrBedfordVan 0:b9164b348919 502
MrBedfordVan 0:b9164b348919 503 ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
MrBedfordVan 0:b9164b348919 504 ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length());
MrBedfordVan 0:b9164b348919 505 ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
MrBedfordVan 0:b9164b348919 506 ble->setAdvertisingInterval(200);
MrBedfordVan 0:b9164b348919 507
MrBedfordVan 0:b9164b348919 508 ble->gap().setAdvertisingTimeout(0);
MrBedfordVan 0:b9164b348919 509 ble->gap().startAdvertising();
MrBedfordVan 0:b9164b348919 510
MrBedfordVan 0:b9164b348919 511 // Stop any running animations on the display
MrBedfordVan 0:b9164b348919 512 display.stopAnimation();
MrBedfordVan 0:b9164b348919 513 display.scroll(msg);
MrBedfordVan 0:b9164b348919 514
MrBedfordVan 0:b9164b348919 515 // Display our name, visualised as a histogram in the display to aid identification.
MrBedfordVan 0:b9164b348919 516 showNameHistogram(display);
MrBedfordVan 0:b9164b348919 517
MrBedfordVan 0:b9164b348919 518 while(1)
MrBedfordVan 0:b9164b348919 519 {
MrBedfordVan 0:b9164b348919 520 if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST)
MrBedfordVan 0:b9164b348919 521 {
MrBedfordVan 0:b9164b348919 522 timeInPairingMode = 0;
MrBedfordVan 0:b9164b348919 523 MicroBitImage arrow("0,0,255,0,0\n0,255,0,0,0\n255,255,255,255,255\n0,255,0,0,0\n0,0,255,0,0\n");
MrBedfordVan 0:b9164b348919 524 display.print(arrow,0,0,0);
MrBedfordVan 0:b9164b348919 525
MrBedfordVan 0:b9164b348919 526 if (fadeDirection == 0)
MrBedfordVan 0:b9164b348919 527 brightness -= MICROBIT_PAIRING_FADE_SPEED;
MrBedfordVan 0:b9164b348919 528 else
MrBedfordVan 0:b9164b348919 529 brightness += MICROBIT_PAIRING_FADE_SPEED;
MrBedfordVan 0:b9164b348919 530
MrBedfordVan 0:b9164b348919 531 if (brightness <= 40)
MrBedfordVan 0:b9164b348919 532 display.clear();
MrBedfordVan 0:b9164b348919 533
MrBedfordVan 0:b9164b348919 534 if (brightness <= 0)
MrBedfordVan 0:b9164b348919 535 fadeDirection = 1;
MrBedfordVan 0:b9164b348919 536
MrBedfordVan 0:b9164b348919 537 if (brightness >= 255)
MrBedfordVan 0:b9164b348919 538 fadeDirection = 0;
MrBedfordVan 0:b9164b348919 539
MrBedfordVan 0:b9164b348919 540 if (authorisationButton.isPressed())
MrBedfordVan 0:b9164b348919 541 {
MrBedfordVan 0:b9164b348919 542 pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST;
MrBedfordVan 0:b9164b348919 543 pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE;
MrBedfordVan 0:b9164b348919 544 }
MrBedfordVan 0:b9164b348919 545 }
MrBedfordVan 0:b9164b348919 546
MrBedfordVan 0:b9164b348919 547 if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE)
MrBedfordVan 0:b9164b348919 548 {
MrBedfordVan 0:b9164b348919 549 timeInPairingMode = 0;
MrBedfordVan 0:b9164b348919 550 display.setBrightness(255);
MrBedfordVan 0:b9164b348919 551 for (int i=0; i<passKey.length(); i++)
MrBedfordVan 0:b9164b348919 552 {
MrBedfordVan 0:b9164b348919 553 display.image.print(passKey.charAt(i),0,0);
MrBedfordVan 0:b9164b348919 554 fiber_sleep(800);
MrBedfordVan 0:b9164b348919 555 display.clear();
MrBedfordVan 0:b9164b348919 556 fiber_sleep(200);
MrBedfordVan 0:b9164b348919 557
MrBedfordVan 0:b9164b348919 558 if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
MrBedfordVan 0:b9164b348919 559 break;
MrBedfordVan 0:b9164b348919 560 }
MrBedfordVan 0:b9164b348919 561
MrBedfordVan 0:b9164b348919 562 fiber_sleep(1000);
MrBedfordVan 0:b9164b348919 563 }
MrBedfordVan 0:b9164b348919 564
MrBedfordVan 0:b9164b348919 565 if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
MrBedfordVan 0:b9164b348919 566 {
MrBedfordVan 0:b9164b348919 567 if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL)
MrBedfordVan 0:b9164b348919 568 {
MrBedfordVan 0:b9164b348919 569 MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n");
MrBedfordVan 0:b9164b348919 570 display.print(tick,0,0,0);
MrBedfordVan 0:b9164b348919 571 fiber_sleep(15000);
MrBedfordVan 0:b9164b348919 572 timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30;
MrBedfordVan 0:b9164b348919 573
MrBedfordVan 0:b9164b348919 574 /*
MrBedfordVan 0:b9164b348919 575 * Disabled, as the API to return the number of active bonds is not reliable at present...
MrBedfordVan 0:b9164b348919 576 *
MrBedfordVan 0:b9164b348919 577 display.clear();
MrBedfordVan 0:b9164b348919 578 ManagedString c(getBondCount());
MrBedfordVan 0:b9164b348919 579 ManagedString c2("/");
MrBedfordVan 0:b9164b348919 580 ManagedString c3(MICROBIT_BLE_MAXIMUM_BONDS);
MrBedfordVan 0:b9164b348919 581 ManagedString c4("USED");
MrBedfordVan 0:b9164b348919 582
MrBedfordVan 0:b9164b348919 583 display.scroll(c+c2+c3+c4);
MrBedfordVan 0:b9164b348919 584 *
MrBedfordVan 0:b9164b348919 585 *
MrBedfordVan 0:b9164b348919 586 */
MrBedfordVan 0:b9164b348919 587 }
MrBedfordVan 0:b9164b348919 588 else
MrBedfordVan 0:b9164b348919 589 {
MrBedfordVan 0:b9164b348919 590 MicroBitImage cross("255,0,0,0,255\n0,255,0,255,0\n0,0,255,0,0\n0,255,0,255,0\n255,0,0,0,255\n");
MrBedfordVan 0:b9164b348919 591 display.print(cross,0,0,0);
MrBedfordVan 0:b9164b348919 592 }
MrBedfordVan 0:b9164b348919 593 }
MrBedfordVan 0:b9164b348919 594
MrBedfordVan 0:b9164b348919 595 fiber_sleep(100);
MrBedfordVan 0:b9164b348919 596 timeInPairingMode++;
MrBedfordVan 0:b9164b348919 597
MrBedfordVan 0:b9164b348919 598 if (timeInPairingMode >= MICROBIT_BLE_PAIRING_TIMEOUT * 30)
MrBedfordVan 0:b9164b348919 599 microbit_reset();
MrBedfordVan 0:b9164b348919 600 }
MrBedfordVan 0:b9164b348919 601 }
MrBedfordVan 0:b9164b348919 602
MrBedfordVan 0:b9164b348919 603 /**
MrBedfordVan 0:b9164b348919 604 * Displays the device's ID code as a histogram on the provided MicroBitDisplay instance.
MrBedfordVan 0:b9164b348919 605 *
MrBedfordVan 0:b9164b348919 606 * @param display The display instance used for displaying the histogram.
MrBedfordVan 0:b9164b348919 607 */
MrBedfordVan 0:b9164b348919 608 void MicroBitBLEManager::showNameHistogram(MicroBitDisplay &display)
MrBedfordVan 0:b9164b348919 609 {
MrBedfordVan 0:b9164b348919 610 uint32_t n = NRF_FICR->DEVICEID[1];
MrBedfordVan 0:b9164b348919 611 int ld = 1;
MrBedfordVan 0:b9164b348919 612 int d = MICROBIT_DFU_HISTOGRAM_HEIGHT;
MrBedfordVan 0:b9164b348919 613 int h;
MrBedfordVan 0:b9164b348919 614
MrBedfordVan 0:b9164b348919 615 display.clear();
MrBedfordVan 0:b9164b348919 616 for (int i=0; i<MICROBIT_DFU_HISTOGRAM_WIDTH;i++)
MrBedfordVan 0:b9164b348919 617 {
MrBedfordVan 0:b9164b348919 618 h = (n % d) / ld;
MrBedfordVan 0:b9164b348919 619
MrBedfordVan 0:b9164b348919 620 n -= h;
MrBedfordVan 0:b9164b348919 621 d *= MICROBIT_DFU_HISTOGRAM_HEIGHT;
MrBedfordVan 0:b9164b348919 622 ld *= MICROBIT_DFU_HISTOGRAM_HEIGHT;
MrBedfordVan 0:b9164b348919 623
MrBedfordVan 0:b9164b348919 624 for (int j=0; j<h+1; j++)
MrBedfordVan 0:b9164b348919 625 display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH-i-1, MICROBIT_DFU_HISTOGRAM_HEIGHT-j-1, 255);
MrBedfordVan 0:b9164b348919 626 }
MrBedfordVan 0:b9164b348919 627 }