updates
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal-eddystone by
Diff: source/bluetooth/MicroBitBLEManager.cpp
- Revision:
- 74:a8f5674a0079
- Parent:
- 66:2fc7d7c2fffc
- Child:
- 75:739b6a1c1b50
--- a/source/bluetooth/MicroBitBLEManager.cpp Wed Jul 13 14:32:54 2016 +0000 +++ b/source/bluetooth/MicroBitBLEManager.cpp Wed Feb 08 07:49:17 2017 +0000 @@ -25,9 +25,10 @@ #include "MicroBitConfig.h" #include "MicroBitBLEManager.h" +#include "MicroBitEddystone.h" #include "MicroBitStorage.h" #include "MicroBitFiber.h" - +#include "MicroBitSystemTimer.h" /* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ. * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL) @@ -42,8 +43,7 @@ #include "ble.h" -extern "C" -{ +extern "C" { #include "device_manager.h" uint32_t btle_set_gatt_table_size(uint32_t size); } @@ -55,13 +55,28 @@ #pragma GCC diagnostic pop #endif -#define MICROBIT_PAIRING_FADE_SPEED 4 +#define MICROBIT_PAIRING_FADE_SPEED 4 -const char* MICROBIT_BLE_MANUFACTURER = NULL; -const char* MICROBIT_BLE_MODEL = "BBC micro:bit"; -const char* MICROBIT_BLE_HARDWARE_VERSION = NULL; -const char* MICROBIT_BLE_FIRMWARE_VERSION = MICROBIT_DAL_VERSION; -const char* MICROBIT_BLE_SOFTWARE_VERSION = NULL; +// +// Local enumeration of valid security modes. Used only to optimise pre‐processor comparisons. +// +#define __SECURITY_MODE_ENCRYPTION_OPEN_LINK 0 +#define __SECURITY_MODE_ENCRYPTION_NO_MITM 1 +#define __SECURITY_MODE_ENCRYPTION_WITH_MITM 2 +// +// Some Black Magic to compare the definition of our security mode in MicroBitConfig with a given parameter. +// Required as the MicroBitConfig option is actually an mbed enum, that is not normally comparable at compile time. +// + +#define __CAT(a, ...) a##__VA_ARGS__ +#define SECURITY_MODE(x) __CAT(__, x) +#define SECURITY_MODE_IS(x) (SECURITY_MODE(MICROBIT_BLE_SECURITY_LEVEL) == SECURITY_MODE(x)) + +const char *MICROBIT_BLE_MANUFACTURER = NULL; +const char *MICROBIT_BLE_MODEL = "BBC micro:bit"; +const char *MICROBIT_BLE_HARDWARE_VERSION = NULL; +const char *MICROBIT_BLE_FIRMWARE_VERSION = MICROBIT_DAL_VERSION; +const char *MICROBIT_BLE_SOFTWARE_VERSION = NULL; const int8_t MICROBIT_BLE_POWER_LEVEL[] = {-30, -20, -16, -12, -8, -4, 0, 4}; /* @@ -69,17 +84,18 @@ * So, we maintain a pointer to the MicroBitBLEManager that's in use. Ths way, we can still access resources on the micro:bit * whilst keeping the code modular. */ -static MicroBitBLEManager *manager = NULL; // Singleton reference to the BLE manager. many mbed BLE API callbacks still do not support member funcions yet. :-( -static uint8_t deviceID = 255; // Unique ID for the peer that has connected to us. -static Gap::Handle_t pairingHandle = 0; // The connection handle used during a pairing process. Used to ensure that connections are dropped elegantly. +MicroBitBLEManager *MicroBitBLEManager::manager = NULL; // Singleton reference to the BLE manager. many mbed BLE API callbacks still do not support member funcions yet. :-( + +static uint8_t deviceID = 255; // Unique ID for the peer that has connected to us. +static Gap::Handle_t pairingHandle = 0; // The connection handle used during a pairing process. Used to ensure that connections are dropped elegantly. static void storeSystemAttributes(Gap::Handle_t handle) { - if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) + if (MicroBitBLEManager::manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) { ManagedString key("bleSysAttrs"); - KeyValuePair* bleSysAttrs = manager->storage->get(key); + KeyValuePair *bleSysAttrs = MicroBitBLEManager::manager->storage->get(key); BLESysAttribute attrib; BLESysAttributeStore attribStore; @@ -89,17 +105,17 @@ sd_ble_gatts_sys_attr_get(handle, attrib.sys_attr, &len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); //copy our stored sysAttrs - if(bleSysAttrs != NULL) + if (bleSysAttrs != NULL) { memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore)); delete bleSysAttrs; } //check if we need to update - if(memcmp(attribStore.sys_attrs[deviceID].sys_attr, attrib.sys_attr, len) != 0) + if (memcmp(attribStore.sys_attrs[deviceID].sys_attr, attrib.sys_attr, len) != 0) { attribStore.sys_attrs[deviceID] = attrib; - manager->storage->put(key, (uint8_t *)&attribStore, sizeof(attribStore)); + MicroBitBLEManager::manager->storage->put(key, (uint8_t *)&attribStore, sizeof(attribStore)); } } } @@ -109,20 +125,20 @@ */ static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *reason) { - MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_DISCONNECTED); + MicroBitEvent(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED); storeSystemAttributes(reason->handle); - if (manager) - manager->advertise(); + if (MicroBitBLEManager::manager) + MicroBitBLEManager::manager->advertise(); } /** * Callback when a BLE connection is established. */ -static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t*) +static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t *) { - MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_CONNECTED); + MicroBitEvent(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED); } /** @@ -133,23 +149,23 @@ int complete = 0; deviceID = 255; - dm_handle_t dm_handle = {0,0,0,0}; + dm_handle_t dm_handle = {0, 0, 0, 0}; int ret = dm_handle_get(params->connHandle, &dm_handle); if (ret == 0) deviceID = dm_handle.device_id; - if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) + if (MicroBitBLEManager::manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) { ManagedString key("bleSysAttrs"); - KeyValuePair* bleSysAttrs = manager->storage->get(key); + KeyValuePair *bleSysAttrs = MicroBitBLEManager::manager->storage->get(key); BLESysAttributeStore attribStore; BLESysAttribute attrib; - if(bleSysAttrs != NULL) + if (bleSysAttrs != NULL) { //restore our sysAttrStore memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore)); @@ -161,40 +177,39 @@ complete = 1; - if(ret == 0) + if (ret == 0) ret = sd_ble_gatts_service_changed(params->connHandle, 0x000c, 0xffff); } } if (!complete) sd_ble_gatts_sys_attr_set(params->connHandle, NULL, 0, 0); - } static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) { - (void) handle; /* -Wunused-param */ + (void)handle; /* -Wunused-param */ - ManagedString passKey((const char *)passkey, SecurityManager::PASSKEY_LEN); + ManagedString passKey((const char *)passkey, SecurityManager::PASSKEY_LEN); - if (manager) - manager->pairingRequested(passKey); + if (MicroBitBLEManager::manager) + MicroBitBLEManager::manager->pairingRequested(passKey); } static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) { - (void) handle; /* -Wunused-param */ + (void)handle; /* -Wunused-param */ - dm_handle_t dm_handle = {0,0,0,0}; + dm_handle_t dm_handle = {0, 0, 0, 0}; int ret = dm_handle_get(handle, &dm_handle); if (ret == 0) deviceID = dm_handle.device_id; - if (manager) + if (MicroBitBLEManager::manager) { pairingHandle = handle; - manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS); + MicroBitBLEManager::manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS); } } @@ -208,12 +223,11 @@ * @note The BLE stack *cannot* be brought up in a static context (the software simply hangs or corrupts itself). * Hence, the init() member function should be used to initialise the BLE stack. */ -MicroBitBLEManager::MicroBitBLEManager(MicroBitStorage& _storage) : - storage(&_storage) +MicroBitBLEManager::MicroBitBLEManager(MicroBitStorage &_storage) : storage(&_storage) { manager = this; - this->ble = NULL; - this->pairingStatus = 0; + this->ble = NULL; + this->pairingStatus = 0; } /** @@ -224,12 +238,24 @@ * @note The BLE stack *cannot* be brought up in a static context (the software simply hangs or corrupts itself). * Hence, the init() member function should be used to initialise the BLE stack. */ -MicroBitBLEManager::MicroBitBLEManager() : - storage(NULL) +MicroBitBLEManager::MicroBitBLEManager() : storage(NULL) { manager = this; - this->ble = NULL; - this->pairingStatus = 0; + this->ble = NULL; + this->pairingStatus = 0; +} + +/** + * When called, the micro:bit will begin advertising for a predefined period, + * MICROBIT_BLE_ADVERTISING_TIMEOUT seconds to bonded devices. + */ +MicroBitBLEManager *MicroBitBLEManager::getInstance() +{ + if (manager == 0) + { + manager = new MicroBitBLEManager; + } + return manager; } /** @@ -238,7 +264,7 @@ */ void MicroBitBLEManager::advertise() { - if(ble) + if (ble) ble->gap().startAdvertising(); } @@ -255,18 +281,18 @@ * bleManager.init(uBit.getName(), uBit.getSerial(), uBit.messageBus, true); * @endcode */ -void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber, EventModel& messageBus, bool enableBonding) +void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber, EventModel &messageBus, bool enableBonding) { - ManagedString BLEName("BBC micro:bit"); - this->deviceName = deviceName; + ManagedString BLEName("BBC micro:bit"); + this->deviceName = deviceName; #if !(CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)) - ManagedString namePrefix(" ["); - ManagedString namePostfix("]"); - BLEName = BLEName + namePrefix + deviceName + namePostfix; + ManagedString namePrefix(" ["); + ManagedString namePostfix("]"); + BLEName = BLEName + namePrefix + deviceName + namePostfix; #endif - // Start the BLE stack. +// Start the BLE stack. #if CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD) btle_set_gatt_table_size(MICROBIT_SD_GATT_TABLE_SIZE); #endif @@ -289,14 +315,26 @@ sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt); #if CONFIG_ENABLED(MICROBIT_BLE_PRIVATE_ADDRESSES) - // Configure for private addresses, so kids' behaviour can't be easily tracked. - ble->gap().setAddress(BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, {0}); + // Configure for private addresses, so kids' behaviour can't be easily tracked. + ble->gap().setAddress(BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, {0}); #endif // Setup our security requirements. ble->securityManager().onPasskeyDisplay(passkeyDisplayCallback); ble->securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); - ble->securityManager().init(enableBonding, (SecurityManager::MICROBIT_BLE_SECURITY_LEVEL == SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM), SecurityManager::IO_CAPS_DISPLAY_ONLY); +// @bluetooth_mdw: select either passkey pairing (more secure), "just works" pairing (less secure but nice and simple for the user) +// or no security +// Default to passkey pairing with MITM protection +#if (SECURITY_MODE_IS(SECURITY_MODE_ENCRYPTION_NO_MITM)) + // Just Works + ble->securityManager().init(enableBonding, false, SecurityManager::IO_CAPS_NONE); +#elif (SECURITY_MODE_IS(SECURITY_MODE_ENCRYPTION_OPEN_LINK)) + // no security + ble->securityManager().init(false, false, SecurityManager::IO_CAPS_DISPLAY_ONLY); +#else + // passkey + ble->securityManager().init(enableBonding, true, SecurityManager::IO_CAPS_DISPLAY_ONLY); +#endif if (enableBonding) { @@ -329,13 +367,13 @@ // Configure the radio at our default power level setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER); - // Bring up core BLE services. +// Bring up core BLE services. #if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE) new MicroBitDFUService(*ble); #endif #if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE) - 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); + 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); #else (void)serialNumber; #endif @@ -346,16 +384,15 @@ (void)messageBus; #endif - // Configure for high speed mode where possible. Gap::ConnectionParams_t fast; ble->getPreferredConnectionParams(&fast); - fast.minConnectionInterval = 8; // 10 ms + fast.minConnectionInterval = 8; // 10 ms fast.maxConnectionInterval = 16; // 20 ms fast.slaveLatency = 0; ble->setPreferredConnectionParams(&fast); - // Setup advertising. +// Setup advertising. #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); #else @@ -370,9 +407,9 @@ ble->gap().setAdvertisingTimeout(MICROBIT_BLE_ADVERTISING_TIMEOUT); #endif - // If we have whitelisting enabled, then prevent only enable advertising of we have any binded devices... - // This is to further protect kids' privacy. If no-one initiates BLE, then the device is unreachable. - // If whiltelisting is disabled, then we always advertise. +// If we have whitelisting enabled, then prevent only enable advertising of we have any binded devices... +// This is to further protect kids' privacy. If no-one initiates BLE, then the device is unreachable. +// If whiltelisting is disabled, then we always advertise. #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) if (whitelist.size > 0) #endif @@ -427,8 +464,8 @@ void MicroBitBLEManager::pairingRequested(ManagedString passKey) { // Update our mode to display the passkey. - this->passKey = passKey; - this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST; + this->passKey = passKey; + this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST; } /** @@ -439,11 +476,13 @@ */ void MicroBitBLEManager::pairingComplete(bool success) { - this->pairingStatus = MICROBIT_BLE_PAIR_COMPLETE; + this->pairingStatus = MICROBIT_BLE_PAIR_COMPLETE; + + pairing_completed_at_time = system_timer_current_time(); - if(success) + if (success) { - this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL; + this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL; fiber_add_idle_component(this); } } @@ -454,11 +493,115 @@ */ void MicroBitBLEManager::idleTick() { - if (ble) - ble->disconnect(pairingHandle, Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF); + if((system_timer_current_time() - pairing_completed_at_time) >= MICROBIT_BLE_DISCONNECT_AFTER_PAIRING_DELAY) { + if (ble) + ble->disconnect(pairingHandle, Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF); + fiber_remove_idle_component(this); + } + +} + + +/** +* Stops any currently running BLE advertisements +*/ +void MicroBitBLEManager::stopAdvertising() +{ + ble->gap().stopAdvertising(); +} + +#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL) +/** + * Set the content of Eddystone URL frames + * + * @param url The url to broadcast + * + * @param calibratedPower the transmission range of the beacon (Defaults to: 0xF0 ~10m). + * + * @param connectable true to keep bluetooth connectable for other services, false otherwise. (Defaults to true) + * + * @param interval the rate at which the micro:bit will advertise url frames. (Defaults to MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL) + * + * @note The calibratedPower value ranges from -100 to +20 to a resolution of 1. The calibrated power should be binary encoded. + * More information can be found at https://github.com/google/eddystone/tree/master/eddystone-uid#tx-power + */ +int MicroBitBLEManager::advertiseEddystoneUrl(const char* url, int8_t calibratedPower, bool connectable, uint16_t interval) +{ + ble->gap().stopAdvertising(); + ble->clearAdvertisingPayload(); + + ble->setAdvertisingType(connectable ? GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED : GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); + ble->setAdvertisingInterval(interval); + + ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); + + int ret = MicroBitEddystone::getInstance()->setURL(ble, url, calibratedPower); + +#if (MICROBIT_BLE_ADVERTISING_TIMEOUT > 0) + ble->gap().setAdvertisingTimeout(MICROBIT_BLE_ADVERTISING_TIMEOUT); +#endif + ble->gap().startAdvertising(); + + return ret; +} - fiber_remove_idle_component(this); +/** + * Set the content of Eddystone URL frames, but accepts a ManagedString as a url. + * + * @param url The url to broadcast + * + * @param calibratedPower the transmission range of the beacon (Defaults to: 0xF0 ~10m). + * + * @param connectable true to keep bluetooth connectable for other services, false otherwise. (Defaults to true) + * + * @param interval the rate at which the micro:bit will advertise url frames. (Defaults to MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL) + * + * @note The calibratedPower value ranges from -100 to +20 to a resolution of 1. The calibrated power should be binary encoded. + * More information can be found at https://github.com/google/eddystone/tree/master/eddystone-uid#tx-power + */ +int MicroBitBLEManager::advertiseEddystoneUrl(ManagedString url, int8_t calibratedPower, bool connectable, uint16_t interval) +{ + return advertiseEddystoneUrl((char *)url.toCharArray(), calibratedPower, connectable, interval); } +#endif + +#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID) +/** + * Set the content of Eddystone UID frames + * + * @param uid_namespace: the uid namespace. Must 10 bytes long. + * + * @param uid_instance: the uid instance value. Must 6 bytes long. + * + * @param calibratedPower the transmission range of the beacon (Defaults to: 0xF0 ~10m). + * + * @param connectable true to keep bluetooth connectable for other services, false otherwise. (Defaults to true) + * + * @param interval the rate at which the micro:bit will advertise url frames. (Defaults to MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL) + * + * @note The calibratedPower value ranges from -100 to +20 to a resolution of 1. The calibrated power should be binary encoded. + * More information can be found at https://github.com/google/eddystone/tree/master/eddystone-uid#tx-power + */ +int MicroBitBLEManager::advertiseEddystoneUid(const char* uid_namespace, const char* uid_instance, int8_t calibratedPower, bool connectable, uint16_t interval) +{ + ble->gap().stopAdvertising(); + ble->clearAdvertisingPayload(); + + ble->setAdvertisingType(connectable ? GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED : GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); + ble->setAdvertisingInterval(interval); + + ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); + + int ret = MicroBitEddystone::getInstance()->setUID(ble, uid_namespace, uid_instance, calibratedPower); + +#if (MICROBIT_BLE_ADVERTISING_TIMEOUT > 0) + ble->gap().setAdvertisingTimeout(MICROBIT_BLE_ADVERTISING_TIMEOUT); +#endif + ble->gap().startAdvertising(); + + return ret; +} +#endif /** * Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming @@ -472,21 +615,21 @@ * bleManager.pairingMode(uBit.display, uBit.buttonA); * @endcode */ -void MicroBitBLEManager::pairingMode(MicroBitDisplay& display, MicroBitButton& authorisationButton) +void MicroBitBLEManager::pairingMode(MicroBitDisplay &display, MicroBitButton &authorisationButton) { - ManagedString namePrefix("BBC micro:bit ["); - ManagedString namePostfix("]"); - ManagedString BLEName = namePrefix + deviceName + namePostfix; + ManagedString namePrefix("BBC micro:bit ["); + ManagedString namePostfix("]"); + ManagedString BLEName = namePrefix + deviceName + namePostfix; - ManagedString msg("PAIRING MODE!"); + ManagedString msg("PAIRING MODE!"); - int timeInPairingMode = 0; - int brightness = 255; - int fadeDirection = 0; + int timeInPairingMode = 0; + int brightness = 255; + int fadeDirection = 0; ble->gap().stopAdvertising(); - // Clear the whitelist (if we have one), so that we're discoverable by all BLE devices. +// Clear the whitelist (if we have one), so that we're discoverable by all BLE devices. #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) BLEProtocol::Address_t addresses[MICROBIT_BLE_MAXIMUM_BONDS]; Gap::Whitelist_t whitelist; @@ -497,7 +640,7 @@ ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); #endif - // Update the advertised name of this micro:bit to include the device name + // Update the advertised name of this micro:bit to include the device name ble->clearAdvertisingPayload(); ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); @@ -508,68 +651,68 @@ ble->gap().setAdvertisingTimeout(0); ble->gap().startAdvertising(); - // Stop any running animations on the display - display.stopAnimation(); - display.scroll(msg); + // Stop any running animations on the display + display.stopAnimation(); + display.scroll(msg); - // Display our name, visualised as a histogram in the display to aid identification. - showNameHistogram(display); + // Display our name, visualised as a histogram in the display to aid identification. + showNameHistogram(display); - while(1) - { - if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST) - { - timeInPairingMode = 0; - 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"); - display.print(arrow,0,0,0); + while (1) + { + if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST) + { + timeInPairingMode = 0; + 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"); + display.print(arrow, 0, 0, 0); - if (fadeDirection == 0) - brightness -= MICROBIT_PAIRING_FADE_SPEED; - else - brightness += MICROBIT_PAIRING_FADE_SPEED; + if (fadeDirection == 0) + brightness -= MICROBIT_PAIRING_FADE_SPEED; + else + brightness += MICROBIT_PAIRING_FADE_SPEED; - if (brightness <= 40) - display.clear(); + if (brightness <= 40) + display.clear(); - if (brightness <= 0) - fadeDirection = 1; + if (brightness <= 0) + fadeDirection = 1; - if (brightness >= 255) - fadeDirection = 0; + if (brightness >= 255) + fadeDirection = 0; - if (authorisationButton.isPressed()) - { - pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST; - pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE; - } - } + if (authorisationButton.isPressed()) + { + pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST; + pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE; + } + } - if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE) - { - timeInPairingMode = 0; - display.setBrightness(255); - for (int i=0; i<passKey.length(); i++) - { - display.image.print(passKey.charAt(i),0,0); - fiber_sleep(800); - display.clear(); - fiber_sleep(200); + if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE) + { + timeInPairingMode = 0; + display.setBrightness(255); + for (int i = 0; i < passKey.length(); i++) + { + display.image.print(passKey.charAt(i), 0, 0); + fiber_sleep(800); + display.clear(); + fiber_sleep(200); - if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) - break; - } + if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) + break; + } - fiber_sleep(1000); - } + fiber_sleep(1000); + } - if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) - { - if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL) - { - 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"); - display.print(tick,0,0,0); + if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE) + { + if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL) + { + 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"); + display.print(tick, 0, 0, 0); fiber_sleep(15000); - timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30; + timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30; /* * Disabled, as the API to return the number of active bonds is not reliable at present... @@ -584,20 +727,20 @@ * * */ - } - else - { - 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"); - display.print(cross,0,0,0); - } - } + } + else + { + 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"); + display.print(cross, 0, 0, 0); + } + } - fiber_sleep(100); - timeInPairingMode++; + fiber_sleep(100); + timeInPairingMode++; - if (timeInPairingMode >= MICROBIT_BLE_PAIRING_TIMEOUT * 30) - microbit_reset(); - } + if (timeInPairingMode >= MICROBIT_BLE_PAIRING_TIMEOUT * 30) + microbit_reset(); + } } /** @@ -613,7 +756,7 @@ int h; display.clear(); - for (int i=0; i<MICROBIT_DFU_HISTOGRAM_WIDTH;i++) + for (int i = 0; i < MICROBIT_DFU_HISTOGRAM_WIDTH; i++) { h = (n % d) / ld; @@ -621,7 +764,7 @@ d *= MICROBIT_DFU_HISTOGRAM_HEIGHT; ld *= MICROBIT_DFU_HISTOGRAM_HEIGHT; - for (int j=0; j<h+1; j++) - display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH-i-1, MICROBIT_DFU_HISTOGRAM_HEIGHT-j-1, 255); + for (int j = 0; j < h + 1; j++) + display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH - i - 1, MICROBIT_DFU_HISTOGRAM_HEIGHT - j - 1, 255); } -} \ No newline at end of file +}