From 1d76def8fa716ab8abf7cef85bd26904d4bc09c9 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Thu, 8 Oct 2015 23:23:00 +0100 Subject: [PATCH 1/4] microbit: BLE service bugfixes Updates to BLE interface to match specification following testing by Bluetooth SIG. Accelerometer Period: now supports READ and WRITE Magnetometer Period: now supports READ and WRITE LED Matrix State: now supports READ and WRITE. UUIDs of Temperature Service characteristic corrected. --- source/ble-services/MicroBitAccelerometerService.cpp | 2 +- source/ble-services/MicroBitLEDService.cpp | 2 +- source/ble-services/MicroBitMagnetometerService.cpp | 2 +- source/ble-services/MicroBitTemperatureService.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/ble-services/MicroBitAccelerometerService.cpp b/source/ble-services/MicroBitAccelerometerService.cpp index 3a2cb08..ab76a8c 100644 --- a/source/ble-services/MicroBitAccelerometerService.cpp +++ b/source/ble-services/MicroBitAccelerometerService.cpp @@ -22,7 +22,7 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) : GattCharacteristic accelerometerPeriodCharacteristic(MicroBitAccelerometerServicePeriodUUID, (uint8_t *)&accelerometerPeriodCharacteristicBuffer, 0, sizeof(accelerometerPeriodCharacteristicBuffer), - GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); // Initialise our characteristic values. accelerometerDataCharacteristicBuffer[0] = 0; diff --git a/source/ble-services/MicroBitLEDService.cpp b/source/ble-services/MicroBitLEDService.cpp index 99538ae..6c935be 100644 --- a/source/ble-services/MicroBitLEDService.cpp +++ b/source/ble-services/MicroBitLEDService.cpp @@ -16,7 +16,7 @@ MicroBitLEDService::MicroBitLEDService(BLEDevice &_ble) : ble(_ble), matrixCharacteristic(MicroBitLEDServiceMatrixUUID, (uint8_t *)&matrixCharacteristicBuffer, 0, sizeof(matrixCharacteristicBuffer), - GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) { // Create the data structures that represent each of our characteristics in Soft Device. GattCharacteristic textCharacteristic(MicroBitLEDServiceTextUUID, (uint8_t *)textCharacteristicBuffer, 0, MICROBIT_BLE_MAXIMUM_SCROLLTEXT, diff --git a/source/ble-services/MicroBitMagnetometerService.cpp b/source/ble-services/MicroBitMagnetometerService.cpp index b4d4b47..2af76e6 100644 --- a/source/ble-services/MicroBitMagnetometerService.cpp +++ b/source/ble-services/MicroBitMagnetometerService.cpp @@ -25,7 +25,7 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) : GattCharacteristic magnetometerPeriodCharacteristic(MicroBitMagnetometerServicePeriodUUID, (uint8_t *)&magnetometerPeriodCharacteristicBuffer, 0, sizeof(magnetometerPeriodCharacteristicBuffer), - GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); // Initialise our characteristic values. magnetometerDataCharacteristicBuffer[0] = 0; diff --git a/source/ble-services/MicroBitTemperatureService.cpp b/source/ble-services/MicroBitTemperatureService.cpp index 014737f..c6be771 100644 --- a/source/ble-services/MicroBitTemperatureService.cpp +++ b/source/ble-services/MicroBitTemperatureService.cpp @@ -51,7 +51,7 @@ const uint8_t MicroBitTemperatureServiceUUID[] = { }; const uint8_t MicroBitTemperatureServiceDataUUID[] = { - 0xe9,0x5d,0x8a,0x38,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 + 0xe9,0x5d,0x92,0x50,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 }; From ce2cc57bf1c13ef09e41f34497c8c4703e9c8be1 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Thu, 8 Oct 2015 23:49:14 +0100 Subject: [PATCH 2/4] microbit: Optimisation of internal Message Bus listeners All message bus listeners with the micro:bit runtie are non blocking, and safe to be called in an interrupt context. As such, these have now all been declared MESSAGE_BUS_LISTENER_IMMEDIATE which should mitigate all unbounded event queueing effects. --- inc/MicroBitListener.h | 2 ++ source/MicroBitFiber.cpp | 2 +- source/MicroBitMultiButton.cpp | 4 ++-- source/ble-services/MicroBitAccelerometerService.cpp | 2 +- source/ble-services/MicroBitButtonService.cpp | 4 ++-- source/ble-services/MicroBitEventService.cpp | 2 +- source/ble-services/MicroBitMagnetometerService.cpp | 2 +- source/ble-services/MicroBitTemperatureService.cpp | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/inc/MicroBitListener.h b/inc/MicroBitListener.h index 46f2939..af7bf22 100644 --- a/inc/MicroBitListener.h +++ b/inc/MicroBitListener.h @@ -14,6 +14,8 @@ #define MESSAGE_BUS_LISTENER_DROP_IF_BUSY 0x0020 #define MESSAGE_BUS_LISTENER_NONBLOCKING 0x0040 #define MESSAGE_BUS_LISTENER_URGENT 0x0080 +#define MESSAGE_BUS_LISTENER_IMMEDIATE (MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT) + struct MicroBitListener { diff --git a/source/MicroBitFiber.cpp b/source/MicroBitFiber.cpp index 67b3351..3c41084 100644 --- a/source/MicroBitFiber.cpp +++ b/source/MicroBitFiber.cpp @@ -310,7 +310,7 @@ void fiber_wait_for_event(uint16_t id, uint16_t value) queue_fiber(f, &waitQueue); // Register to receive this event, so we can wake up the fiber when it happens. - uBit.MessageBus.listen(id, value, scheduler_event, MESSAGE_BUS_LISTENER_NONBLOCKING); + uBit.MessageBus.listen(id, value, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE); // Finally, enter the scheduler. schedule(); diff --git a/source/MicroBitMultiButton.cpp b/source/MicroBitMultiButton.cpp index b37bbb5..f477756 100644 --- a/source/MicroBitMultiButton.cpp +++ b/source/MicroBitMultiButton.cpp @@ -35,8 +35,8 @@ MicroBitMultiButton::MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t this->button1 = button1; this->button2 = button2; - uBit.MessageBus.listen(button1, MICROBIT_EVT_ANY, onMultiButtonEvent); - uBit.MessageBus.listen(button2, MICROBIT_EVT_ANY, onMultiButtonEvent); + uBit.MessageBus.listen(button1, MICROBIT_EVT_ANY, onMultiButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE); + uBit.MessageBus.listen(button2, MICROBIT_EVT_ANY, onMultiButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE); } uint16_t MicroBitMultiButton::otherSubButton(uint16_t b) diff --git a/source/ble-services/MicroBitAccelerometerService.cpp b/source/ble-services/MicroBitAccelerometerService.cpp index ab76a8c..3ab777f 100644 --- a/source/ble-services/MicroBitAccelerometerService.cpp +++ b/source/ble-services/MicroBitAccelerometerService.cpp @@ -42,7 +42,7 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) : ble.gattServer().write(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer)); ble.onDataWritten(this, &MicroBitAccelerometerService::onDataWritten); - uBit.MessageBus.listen(MICROBIT_ID_ACCELEROMETER, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE, this, &MicroBitAccelerometerService::accelerometerUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT); + uBit.MessageBus.listen(MICROBIT_ID_ACCELEROMETER, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE, this, &MicroBitAccelerometerService::accelerometerUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE); } /** diff --git a/source/ble-services/MicroBitButtonService.cpp b/source/ble-services/MicroBitButtonService.cpp index 459b7ac..e752298 100644 --- a/source/ble-services/MicroBitButtonService.cpp +++ b/source/ble-services/MicroBitButtonService.cpp @@ -39,8 +39,8 @@ MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble) : ble.gattServer().write(buttonADataCharacteristicHandle,(uint8_t *)&buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer)); ble.gattServer().write(buttonBDataCharacteristicHandle,(uint8_t *)&buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer)); - uBit.MessageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonAUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT); - uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonBUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT); + uBit.MessageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonAUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE); + uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonBUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE); } diff --git a/source/ble-services/MicroBitEventService.cpp b/source/ble-services/MicroBitEventService.cpp index 6719d98..6f76f04 100644 --- a/source/ble-services/MicroBitEventService.cpp +++ b/source/ble-services/MicroBitEventService.cpp @@ -73,7 +73,7 @@ void MicroBitEventService::onDataWritten(const GattWriteCallbackParams *params) // Read and register for all the events given... while (len >= 4) { - uBit.MessageBus.listen(e->type, e->reason, this, &MicroBitEventService::onMicroBitEvent, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT); + uBit.MessageBus.listen(e->type, e->reason, this, &MicroBitEventService::onMicroBitEvent, MESSAGE_BUS_LISTENER_IMMEDIATE); len-=4; e++; diff --git a/source/ble-services/MicroBitMagnetometerService.cpp b/source/ble-services/MicroBitMagnetometerService.cpp index 2af76e6..3bbf944 100644 --- a/source/ble-services/MicroBitMagnetometerService.cpp +++ b/source/ble-services/MicroBitMagnetometerService.cpp @@ -48,7 +48,7 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) : ble.gattServer().write(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer)); ble.onDataWritten(this, &MicroBitMagnetometerService::onDataWritten); - uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_DATA_UPDATE, this, &MicroBitMagnetometerService::magnetometerUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT); + uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_DATA_UPDATE, this, &MicroBitMagnetometerService::magnetometerUpdate); uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CONFIG_NEEDED, this, &MicroBitMagnetometerService::samplePeriodUpdateNeeded); } diff --git a/source/ble-services/MicroBitTemperatureService.cpp b/source/ble-services/MicroBitTemperatureService.cpp index c6be771..c1e7790 100644 --- a/source/ble-services/MicroBitTemperatureService.cpp +++ b/source/ble-services/MicroBitTemperatureService.cpp @@ -31,7 +31,7 @@ MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) : temperatureDataCharacteristicHandle = temperatureDataCharacteristic.getValueHandle(); ble.gattServer().write(temperatureDataCharacteristicHandle,(uint8_t *)&temperatureDataCharacteristicBuffer, sizeof(temperatureDataCharacteristicBuffer)); - uBit.MessageBus.listen(MICROBIT_ID_THERMOMETER, MICROBIT_THERMOMETER_EVT_UPDATE, this, &MicroBitTemperatureService::temperatureUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT); + uBit.MessageBus.listen(MICROBIT_ID_THERMOMETER, MICROBIT_THERMOMETER_EVT_UPDATE, this, &MicroBitTemperatureService::temperatureUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE); } /** From 122d885ee8c4075827c88b293351a8539d8c4cbe Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 9 Oct 2015 00:03:01 +0100 Subject: [PATCH 3/4] microbit: Updated Bluetooth device name from MicroBit to micro:bit to match brand guidelines --- source/MicroBit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/MicroBit.cpp b/source/MicroBit.cpp index e99aa96..56006b2 100644 --- a/source/MicroBit.cpp +++ b/source/MicroBit.cpp @@ -1,10 +1,10 @@ #include "MicroBit.h" -char MICROBIT_BLE_DEVICE_NAME[] = "BBC MicroBit [xxxxx]"; +char MICROBIT_BLE_DEVICE_NAME[] = "BBC micro:bit [xxxxx]"; #if CONFIG_ENABLED(MICROBIT_BLE_ENABLED) && CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE) const char MICROBIT_BLE_MANUFACTURER[] = "The Cast of W1A"; -const char MICROBIT_BLE_MODEL[] = "Microbit SB2"; +const char MICROBIT_BLE_MODEL[] = "micro:bit"; const char MICROBIT_BLE_SERIAL[] = "SN1"; const char MICROBIT_BLE_HARDWARE_VERSION[] = "0.2"; const char MICROBIT_BLE_FIRMWARE_VERSION[] = "1.1"; @@ -107,7 +107,7 @@ void MicroBit::init() ble_firmware_update_service = new MicroBitDFUService(*ble); // Compute our auto-generated MicroBit device name. - ble_firmware_update_service->getName(MICROBIT_BLE_DEVICE_NAME+14); + ble_firmware_update_service->getName(MICROBIT_BLE_DEVICE_NAME+15); #endif #if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE) From 6764c732eaa2d4b1f050bd4d68f942f8e66e91f3 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 9 Oct 2015 01:14:36 +0100 Subject: [PATCH 4/4] microbit: BUGFIX to MicroBtDFU Service - Updates to UI handling to avoid starving out the processor. - Clears screen before entering DFU bootloader --- inc/MicroBitDFUService.h | 4 ++ source/ble-services/MicroBitDFUService.cpp | 72 ++++++++++++---------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/inc/MicroBitDFUService.h b/inc/MicroBitDFUService.h index 1d94f32..9d6c3cb 100644 --- a/inc/MicroBitDFUService.h +++ b/inc/MicroBitDFUService.h @@ -92,6 +92,10 @@ class MicroBitDFUService // Update BLE characteristic to release our flash code. void releaseFlashCode(); + + // Event handlers for button clicks. + void onButtonA(MicroBitEvent e); + void onButtonB(MicroBitEvent e); }; #endif diff --git a/source/ble-services/MicroBitDFUService.cpp b/source/ble-services/MicroBitDFUService.cpp index defd65b..b88ccce 100644 --- a/source/ble-services/MicroBitDFUService.cpp +++ b/source/ble-services/MicroBitDFUService.cpp @@ -46,7 +46,7 @@ MicroBitDFUService::MicroBitDFUService(BLEDevice &_ble) : microBitDFUServiceControlCharacteristicHandle = microBitDFUServiceControlCharacteristic.getValueHandle(); microBitDFUServiceFlashCodeCharacteristicHandle = microBitDFUServiceFlashCodeCharacteristic.getValueHandle(); - ble.onDataWritten(this, &MicroBitDFUService::onDataWritten); + ble.gattServer().onDataWritten(this, &MicroBitDFUService::onDataWritten); } @@ -88,54 +88,54 @@ int MicroBitDFUService::getName(char *name) return MICROBIT_DFU_HISTOGRAM_WIDTH; } +void MicroBitDFUService::onButtonA(MicroBitEvent e) +{ + if (flashCodeRequested) + { + releaseFlashCode(); + uBit.display.scroll(""); + showTick(); + flashCodeRequested = false; + authenticated = true; + } +} + +void MicroBitDFUService::onButtonB(MicroBitEvent e) +{ + uBit.display.scroll("VERSION: TODO"); + showNameHistogram(); +} + /** * Begin the pairing process. Typically called when device is powered up with buttons held down. * Scroll a description on the display, then displays the device ID code as a histogram on the matrix display. */ void MicroBitDFUService::pair() { - ManagedString blueZoneString("BLUE ZONE..."); - ManagedString pairString("PAIR?"); - - uBit.display.scroll(blueZoneString); + uBit.MessageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, this, &MicroBitDFUService::onButtonA); + uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, this, &MicroBitDFUService::onButtonB); + uBit.display.scroll("BLUE ZONE..."); showNameHistogram(); while(1) { - for (int i=0; i<100; i++) - { - if (flashCodeRequested) - { - uBit.display.scrollAsync(pairString); - for (int j=0; j<40; j++) - { - if (uBit.buttonA.isPressed()) - { - i=100; - releaseFlashCode(); - showTick(); - flashCodeRequested = false; - authenticated = true; - break; - } - - wait(0.1); - } - } - wait (0.1); + if (flashCodeRequested) + uBit.display.scroll("PAIR?"); - // If our peer disconnects, drop all state. - if ((authenticated || flashCodeRequested) && !ble.getGapState().connected) - { - authenticated = false; - flashCodeRequested = false; - flashCode = 0x00; - } + // If our peer disconnects, drop all state. + if ((authenticated || flashCodeRequested) && !ble.getGapState().connected) + { + authenticated = false; + flashCodeRequested = false; + flashCode = 0x00; } + + uBit.sleep(500); } } + /** * Callback. Invoked when any of our attributes are written via BLE. */ @@ -152,6 +152,9 @@ void MicroBitDFUService::onDataWritten(const GattWriteCallbackParams *params) if (authenticated) { + uBit.display.scroll(""); + uBit.display.clear(); + #if CONFIG_ENABLED(MICROBIT_DBG) pc.printf(" ACTIVATING BOOTLOADER.\n"); #endif @@ -161,6 +164,9 @@ void MicroBitDFUService::onDataWritten(const GattWriteCallbackParams *params) break; case MICROBIT_DFU_OPCODE_START_PAIR: +#if CONFIG_ENABLED(MICROBIT_DBG) + pc.printf(" PAIRING REQUESTED.\n"); +#endif flashCodeRequested = true; break;