mbed.org local branch of microbit-dal. The real version lives in git at https://github.com/lancaster-university/microbit-dal

Dependencies:   BLE_API nRF51822 mbed-dev-bin

Dependents:   microbit Microbit IoTChallenge1 microbit ... more

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:18:14 2016 +0100
Revision:
35:8ce23bc1af38
Parent:
32:ece16b5987dd
Child:
37:b624ae5e94a5
Synchronized with git rev 732971e7
Author: James Devine
microbit-dal: Added events to MicroBitPin

Added rise, fall, pulse HI and LO events.

The pulse Hi and LO event timestamp given in the MicroBitEvent is the
duration for which the input was HI or LO for.

eventOn(int eventType) is used to configure the events generated
from the pin instance.

Who changed what in which revision?

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