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
MicroBitBLEManager.cpp
00001 /* 00002 The MIT License (MIT) 00003 00004 Copyright (c) 2016 British Broadcasting Corporation. 00005 This software is provided by Lancaster University by arrangement with the BBC. 00006 00007 Permission is hereby granted, free of charge, to any person obtaining a 00008 copy of this software and associated documentation files (the "Software"), 00009 to deal in the Software without restriction, including without limitation 00010 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 and/or sell copies of the Software, and to permit persons to whom the 00012 Software is furnished to do so, subject to the following conditions: 00013 00014 The above copyright notice and this permission notice shall be included in 00015 all copies or substantial portions of the Software. 00016 00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00023 DEALINGS IN THE SOFTWARE. 00024 */ 00025 00026 #include "MicroBitConfig.h" 00027 #include "MicroBitBLEManager.h" 00028 #include "MicroBitStorage.h" 00029 #include "MicroBitFiber.h" 00030 00031 00032 /* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ. 00033 * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL) 00034 * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this 00035 * as a compatability option, but does not support the options used... 00036 */ 00037 #if !defined(__arm) 00038 #pragma GCC diagnostic ignored "-Wunused-function" 00039 #pragma GCC diagnostic push 00040 #pragma GCC diagnostic ignored "-Wunused-parameter" 00041 #endif 00042 00043 #include "ble.h" 00044 00045 extern "C" 00046 { 00047 #include "device_manager.h" 00048 uint32_t btle_set_gatt_table_size(uint32_t size); 00049 } 00050 00051 /* 00052 * Return to our predefined compiler settings. 00053 */ 00054 #if !defined(__arm) 00055 #pragma GCC diagnostic pop 00056 #endif 00057 00058 #define MICROBIT_PAIRING_FADE_SPEED 4 00059 00060 const char* MICROBIT_BLE_MANUFACTURER = NULL; 00061 const char* MICROBIT_BLE_MODEL = "BBC micro:bit"; 00062 const char* MICROBIT_BLE_HARDWARE_VERSION = NULL; 00063 const char* MICROBIT_BLE_FIRMWARE_VERSION = MICROBIT_DAL_VERSION; 00064 const char* MICROBIT_BLE_SOFTWARE_VERSION = NULL; 00065 const int8_t MICROBIT_BLE_POWER_LEVEL[] = {-30, -20, -16, -12, -8, -4, 0, 4}; 00066 00067 /* 00068 * Many of the mbed interfaces we need to use only support callbacks to plain C functions, rather than C++ methods. 00069 * So, we maintain a pointer to the MicroBitBLEManager that's in use. Ths way, we can still access resources on the micro:bit 00070 * whilst keeping the code modular. 00071 */ 00072 static MicroBitBLEManager *manager = NULL; // Singleton reference to the BLE manager. many mbed BLE API callbacks still do not support member funcions yet. :-( 00073 static uint8_t deviceID = 255; // Unique ID for the peer that has connected to us. 00074 static Gap::Handle_t pairingHandle = 0; // The connection handle used during a pairing process. Used to ensure that connections are dropped elegantly. 00075 00076 static void storeSystemAttributes(Gap::Handle_t handle) 00077 { 00078 if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) 00079 { 00080 ManagedString key("bleSysAttrs"); 00081 00082 KeyValuePair* bleSysAttrs = manager->storage->get(key); 00083 00084 BLESysAttribute attrib; 00085 BLESysAttributeStore attribStore; 00086 00087 uint16_t len = sizeof(attrib.sys_attr); 00088 00089 sd_ble_gatts_sys_attr_get(handle, attrib.sys_attr, &len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); 00090 00091 //copy our stored sysAttrs 00092 if(bleSysAttrs != NULL) 00093 { 00094 memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore)); 00095 delete bleSysAttrs; 00096 } 00097 00098 //check if we need to update 00099 if(memcmp(attribStore.sys_attrs[deviceID].sys_attr, attrib.sys_attr, len) != 0) 00100 { 00101 attribStore.sys_attrs[deviceID] = attrib; 00102 manager->storage->put(key, (uint8_t *)&attribStore, sizeof(attribStore)); 00103 } 00104 } 00105 } 00106 00107 /** 00108 * Callback when a BLE GATT disconnect occurs. 00109 */ 00110 static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *reason) 00111 { 00112 MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_DISCONNECTED); 00113 00114 storeSystemAttributes(reason->handle); 00115 00116 if (manager) 00117 manager->advertise(); 00118 } 00119 00120 /** 00121 * Callback when a BLE connection is established. 00122 */ 00123 static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t*) 00124 { 00125 MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_CONNECTED); 00126 } 00127 00128 /** 00129 * Callback when a BLE SYS_ATTR_MISSING. 00130 */ 00131 static void bleSysAttrMissingCallback(const GattSysAttrMissingCallbackParams *params) 00132 { 00133 int complete = 0; 00134 deviceID = 255; 00135 00136 dm_handle_t dm_handle = {0,0,0,0}; 00137 00138 int ret = dm_handle_get(params->connHandle, &dm_handle); 00139 00140 if (ret == 0) 00141 deviceID = dm_handle.device_id; 00142 00143 if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) 00144 { 00145 ManagedString key("bleSysAttrs"); 00146 00147 KeyValuePair* bleSysAttrs = manager->storage->get(key); 00148 00149 BLESysAttributeStore attribStore; 00150 BLESysAttribute attrib; 00151 00152 if(bleSysAttrs != NULL) 00153 { 00154 //restore our sysAttrStore 00155 memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore)); 00156 delete bleSysAttrs; 00157 00158 attrib = attribStore.sys_attrs[deviceID]; 00159 00160 ret = sd_ble_gatts_sys_attr_set(params->connHandle, attrib.sys_attr, sizeof(attrib.sys_attr), BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); 00161 00162 complete = 1; 00163 00164 if(ret == 0) 00165 ret = sd_ble_gatts_service_changed(params->connHandle, 0x000c, 0xffff); 00166 } 00167 } 00168 00169 if (!complete) 00170 sd_ble_gatts_sys_attr_set(params->connHandle, NULL, 0, 0); 00171 00172 } 00173 00174 static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) 00175 { 00176 (void) handle; /* -Wunused-param */ 00177 00178 ManagedString passKey((const char *)passkey, SecurityManager::PASSKEY_LEN); 00179 00180 if (manager) 00181 manager->pairingRequested(passKey); 00182 } 00183 00184 static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) 00185 { 00186 (void) handle; /* -Wunused-param */ 00187 00188 dm_handle_t dm_handle = {0,0,0,0}; 00189 int ret = dm_handle_get(handle, &dm_handle); 00190 00191 if (ret == 0) 00192 deviceID = dm_handle.device_id; 00193 00194 if (manager) 00195 { 00196 pairingHandle = handle; 00197 manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS); 00198 } 00199 } 00200 00201 /** 00202 * Constructor. 00203 * 00204 * Configure and manage the micro:bit's Bluetooth Low Energy (BLE) stack. 00205 * 00206 * @param _storage an instance of MicroBitStorage used to persist sys attribute information. (This is required for compatability with iOS). 00207 * 00208 * @note The BLE stack *cannot* be brought up in a static context (the software simply hangs or corrupts itself). 00209 * Hence, the init() member function should be used to initialise the BLE stack. 00210 */ 00211 MicroBitBLEManager::MicroBitBLEManager(MicroBitStorage& _storage) : 00212 storage(&_storage) 00213 { 00214 manager = this; 00215 this->ble = NULL; 00216 this->pairingStatus = 0; 00217 } 00218 00219 /** 00220 * Constructor. 00221 * 00222 * Configure and manage the micro:bit's Bluetooth Low Energy (BLE) stack. 00223 * 00224 * @note The BLE stack *cannot* be brought up in a static context (the software simply hangs or corrupts itself). 00225 * Hence, the init() member function should be used to initialise the BLE stack. 00226 */ 00227 MicroBitBLEManager::MicroBitBLEManager() : 00228 storage(NULL) 00229 { 00230 manager = this; 00231 this->ble = NULL; 00232 this->pairingStatus = 0; 00233 } 00234 00235 /** 00236 * When called, the micro:bit will begin advertising for a predefined period, 00237 * MICROBIT_BLE_ADVERTISING_TIMEOUT seconds to bonded devices. 00238 */ 00239 void MicroBitBLEManager::advertise() 00240 { 00241 if(ble) 00242 ble->gap().startAdvertising(); 00243 } 00244 00245 /** 00246 * Post constructor initialisation method as the BLE stack cannot be brought 00247 * up in a static context. 00248 * 00249 * @param deviceName The name used when advertising 00250 * @param serialNumber The serial number exposed by the device information service 00251 * @param messageBus An instance of an EventModel, used during pairing. 00252 * @param enableBonding If true, the security manager enabled bonding. 00253 * 00254 * @code 00255 * bleManager.init(uBit.getName(), uBit.getSerial(), uBit.messageBus, true); 00256 * @endcode 00257 */ 00258 void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber, EventModel& messageBus, bool enableBonding) 00259 { 00260 ManagedString BLEName("BBC micro:bit"); 00261 this->deviceName = deviceName; 00262 00263 #if !(CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)) 00264 ManagedString namePrefix(" ["); 00265 ManagedString namePostfix("]"); 00266 BLEName = BLEName + namePrefix + deviceName + namePostfix; 00267 #endif 00268 00269 // Start the BLE stack. 00270 #if CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD) 00271 btle_set_gatt_table_size(MICROBIT_SD_GATT_TABLE_SIZE); 00272 #endif 00273 00274 ble = new BLEDevice(); 00275 ble->init(); 00276 00277 // automatically restart advertising after a device disconnects. 00278 ble->gap().onDisconnection(bleDisconnectionCallback); 00279 ble->gattServer().onSysAttrMissing(bleSysAttrMissingCallback); 00280 00281 // generate an event when a Bluetooth connection is established 00282 ble->gap().onConnection(bleConnectionCallback); 00283 00284 // Configure the stack to hold onto the CPU during critical timing events. 00285 // mbed-classic performs __disable_irq() calls in its timers that can cause 00286 // MIC failures on secure BLE channels... 00287 ble_common_opt_radio_cpu_mutex_t opt; 00288 opt.enable = 1; 00289 sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt); 00290 00291 #if CONFIG_ENABLED(MICROBIT_BLE_PRIVATE_ADDRESSES) 00292 // Configure for private addresses, so kids' behaviour can't be easily tracked. 00293 ble->gap().setAddress(BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, {0}); 00294 #endif 00295 00296 // Setup our security requirements. 00297 ble->securityManager().onPasskeyDisplay(passkeyDisplayCallback); 00298 ble->securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); 00299 ble->securityManager().init(enableBonding, (SecurityManager::MICROBIT_BLE_SECURITY_LEVEL == SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM), SecurityManager::IO_CAPS_DISPLAY_ONLY); 00300 00301 if (enableBonding) 00302 { 00303 // If we're in pairing mode, review the size of the bond table. 00304 int bonds = getBondCount(); 00305 00306 // TODO: It would be much better to implement some sort of LRU/NFU policy here, 00307 // but this isn't currently supported in mbed, so we'd need to layer break... 00308 00309 // If we're full, empty the bond table. 00310 if (bonds >= MICROBIT_BLE_MAXIMUM_BONDS) 00311 ble->securityManager().purgeAllBondingState(); 00312 } 00313 00314 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) 00315 // Configure a whitelist to filter all connection requetss from unbonded devices. 00316 // Most BLE stacks only permit one connection at a time, so this prevents denial of service attacks. 00317 BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS]; 00318 Gap::Whitelist_t whitelist; 00319 whitelist.addresses = bondedAddresses; 00320 whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; 00321 00322 ble->securityManager().getAddressesFromBondTable(whitelist); 00323 00324 ble->gap().setWhitelist(whitelist); 00325 ble->gap().setScanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST); 00326 ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS); 00327 #endif 00328 00329 // Configure the radio at our default power level 00330 setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER); 00331 00332 // Bring up core BLE services. 00333 #if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE) 00334 new MicroBitDFUService(*ble); 00335 #endif 00336 00337 #if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE) 00338 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); 00339 #else 00340 (void)serialNumber; 00341 #endif 00342 00343 #if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE) 00344 new MicroBitEventService(*ble, messageBus); 00345 #else 00346 (void)messageBus; 00347 #endif 00348 00349 00350 // Configure for high speed mode where possible. 00351 Gap::ConnectionParams_t fast; 00352 ble->getPreferredConnectionParams(&fast); 00353 fast.minConnectionInterval = 8; // 10 ms 00354 fast.maxConnectionInterval = 16; // 20 ms 00355 fast.slaveLatency = 0; 00356 ble->setPreferredConnectionParams(&fast); 00357 00358 // Setup advertising. 00359 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) 00360 ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); 00361 #else 00362 ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00363 #endif 00364 00365 ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length()); 00366 ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00367 ble->setAdvertisingInterval(200); 00368 00369 #if (MICROBIT_BLE_ADVERTISING_TIMEOUT > 0) 00370 ble->gap().setAdvertisingTimeout(MICROBIT_BLE_ADVERTISING_TIMEOUT); 00371 #endif 00372 00373 // If we have whitelisting enabled, then prevent only enable advertising of we have any binded devices... 00374 // This is to further protect kids' privacy. If no-one initiates BLE, then the device is unreachable. 00375 // If whiltelisting is disabled, then we always advertise. 00376 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) 00377 if (whitelist.size > 0) 00378 #endif 00379 ble->startAdvertising(); 00380 } 00381 00382 /** 00383 * Change the output power level of the transmitter to the given value. 00384 * 00385 * @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest. 00386 * 00387 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range. 00388 * 00389 * @code 00390 * // maximum transmission power. 00391 * bleManager.setTransmitPower(7); 00392 * @endcode 00393 */ 00394 int MicroBitBLEManager::setTransmitPower(int power) 00395 { 00396 if (power < 0 || power >= MICROBIT_BLE_POWER_LEVELS) 00397 return MICROBIT_INVALID_PARAMETER; 00398 00399 if (ble->gap().setTxPower(MICROBIT_BLE_POWER_LEVEL[power]) != NRF_SUCCESS) 00400 return MICROBIT_NOT_SUPPORTED; 00401 00402 return MICROBIT_OK; 00403 } 00404 00405 /** 00406 * Determines the number of devices currently bonded with this micro:bit. 00407 * @return The number of active bonds. 00408 */ 00409 int MicroBitBLEManager::getBondCount() 00410 { 00411 BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS]; 00412 Gap::Whitelist_t whitelist; 00413 whitelist.addresses = bondedAddresses; 00414 whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; 00415 ble->securityManager().getAddressesFromBondTable(whitelist); 00416 00417 return whitelist.bonds; 00418 } 00419 00420 /** 00421 * A request to pair has been received from a BLE device. 00422 * If we're in pairing mode, display the passkey to the user. 00423 * Also, purge the bonding table if it has reached capacity. 00424 * 00425 * @note for internal use only. 00426 */ 00427 void MicroBitBLEManager::pairingRequested(ManagedString passKey) 00428 { 00429 // Update our mode to display the passkey. 00430 this->passKey = passKey; 00431 this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST; 00432 } 00433 00434 /** 00435 * A pairing request has been sucessfully completed. 00436 * If we're in pairing mode, display a success or failure message. 00437 * 00438 * @note for internal use only. 00439 */ 00440 void MicroBitBLEManager::pairingComplete(bool success) 00441 { 00442 this->pairingStatus = MICROBIT_BLE_PAIR_COMPLETE; 00443 00444 if(success) 00445 { 00446 this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL; 00447 fiber_add_idle_component(this); 00448 } 00449 } 00450 00451 /** 00452 * Periodic callback in thread context. 00453 * We use this here purely to safely issue a disconnect operation after a pairing operation is complete. 00454 */ 00455 void MicroBitBLEManager::idleTick() 00456 { 00457 if (ble) 00458 ble->disconnect(pairingHandle, Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF); 00459 00460 fiber_remove_idle_component(this); 00461 } 00462 00463 /** 00464 * Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming 00465 * of the micro:bit in cases where BLE is disabled during normal operation. 00466 * 00467 * @param display An instance of MicroBitDisplay used when displaying pairing information. 00468 * @param authorizationButton The button to use to authorise a pairing request. 00469 * 00470 * @code 00471 * // initiate pairing mode 00472 * bleManager.pairingMode(uBit.display, uBit.buttonA); 00473 * @endcode 00474 */ 00475 void MicroBitBLEManager::pairingMode(MicroBitDisplay& display, MicroBitButton& authorisationButton) 00476 { 00477 ManagedString namePrefix("BBC micro:bit ["); 00478 ManagedString namePostfix("]"); 00479 ManagedString BLEName = namePrefix + deviceName + namePostfix; 00480 00481 ManagedString msg("PAIRING MODE!"); 00482 00483 int timeInPairingMode = 0; 00484 int brightness = 255; 00485 int fadeDirection = 0; 00486 00487 ble->gap().stopAdvertising(); 00488 00489 // Clear the whitelist (if we have one), so that we're discoverable by all BLE devices. 00490 #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) 00491 BLEProtocol::Address_t addresses[MICROBIT_BLE_MAXIMUM_BONDS]; 00492 Gap::Whitelist_t whitelist; 00493 whitelist.addresses = addresses; 00494 whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; 00495 whitelist.size = 0; 00496 ble->gap().setWhitelist(whitelist); 00497 ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); 00498 #endif 00499 00500 // Update the advertised name of this micro:bit to include the device name 00501 ble->clearAdvertisingPayload(); 00502 00503 ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00504 ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length()); 00505 ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00506 ble->setAdvertisingInterval(200); 00507 00508 ble->gap().setAdvertisingTimeout(0); 00509 ble->gap().startAdvertising(); 00510 00511 // Stop any running animations on the display 00512 display.stopAnimation(); 00513 display.scroll(msg); 00514 00515 // Display our name, visualised as a histogram in the display to aid identification. 00516 showNameHistogram(display); 00517 00518 while(1) 00519 { 00520 if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST) 00521 { 00522 timeInPairingMode = 0; 00523 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"); 00524 display.print(arrow,0,0,0); 00525 00526 if (fadeDirection == 0) 00527 brightness -= MICROBIT_PAIRING_FADE_SPEED; 00528 else 00529 brightness += MICROBIT_PAIRING_FADE_SPEED; 00530 00531 if (brightness <= 40) 00532 display.clear(); 00533 00534 if (brightness <= 0) 00535 fadeDirection = 1; 00536 00537 if (brightness >= 255) 00538 fadeDirection = 0; 00539 00540 if (authorisationButton.isPressed()) 00541 { 00542 pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST; 00543 pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE; 00544 } 00545 } 00546 00547 if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE) 00548 { 00549 timeInPairingMode = 0; 00550 display.setBrightness(255); 00551 for (int i=0; i<passKey.length(); i++) 00552 { 00553 display.image.print(passKey.charAt(i),0,0); 00554 fiber_sleep(800); 00555 display.clear(); 00556 fiber_sleep(200); 00557 00558 if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) 00559 break; 00560 } 00561 00562 fiber_sleep(1000); 00563 } 00564 00565 if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) 00566 { 00567 if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL) 00568 { 00569 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"); 00570 display.print(tick,0,0,0); 00571 fiber_sleep(15000); 00572 timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30; 00573 00574 /* 00575 * Disabled, as the API to return the number of active bonds is not reliable at present... 00576 * 00577 display.clear(); 00578 ManagedString c(getBondCount()); 00579 ManagedString c2("/"); 00580 ManagedString c3(MICROBIT_BLE_MAXIMUM_BONDS); 00581 ManagedString c4("USED"); 00582 00583 display.scroll(c+c2+c3+c4); 00584 * 00585 * 00586 */ 00587 } 00588 else 00589 { 00590 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"); 00591 display.print(cross,0,0,0); 00592 } 00593 } 00594 00595 fiber_sleep(100); 00596 timeInPairingMode++; 00597 00598 if (timeInPairingMode >= MICROBIT_BLE_PAIRING_TIMEOUT * 30) 00599 microbit_reset(); 00600 } 00601 } 00602 00603 /** 00604 * Displays the device's ID code as a histogram on the provided MicroBitDisplay instance. 00605 * 00606 * @param display The display instance used for displaying the histogram. 00607 */ 00608 void MicroBitBLEManager::showNameHistogram(MicroBitDisplay &display) 00609 { 00610 uint32_t n = NRF_FICR->DEVICEID[1]; 00611 int ld = 1; 00612 int d = MICROBIT_DFU_HISTOGRAM_HEIGHT; 00613 int h; 00614 00615 display.clear(); 00616 for (int i=0; i<MICROBIT_DFU_HISTOGRAM_WIDTH;i++) 00617 { 00618 h = (n % d) / ld; 00619 00620 n -= h; 00621 d *= MICROBIT_DFU_HISTOGRAM_HEIGHT; 00622 ld *= MICROBIT_DFU_HISTOGRAM_HEIGHT; 00623 00624 for (int j=0; j<h+1; j++) 00625 display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH-i-1, MICROBIT_DFU_HISTOGRAM_HEIGHT-j-1, 255); 00626 } 00627 }
Generated on Tue Jul 12 2022 15:22:55 by 1.7.2