From 380b99944066e7bb7b14d977c038d84f7c884b0a Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Tue, 8 Sep 2015 13:55:15 +0100 Subject: [PATCH] microbit: BUGFIX: read callbacks on working Changes to MicroBitLEDService class to ensure matrixCharacteristic remains persistent. Needed to allow mbed read callbacks. --- inc/MicroBitLEDService.h | 59 +++++++++ source/ble-services/MicroBitLEDService.cpp | 135 +++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 inc/MicroBitLEDService.h create mode 100644 source/ble-services/MicroBitLEDService.cpp diff --git a/inc/MicroBitLEDService.h b/inc/MicroBitLEDService.h new file mode 100644 index 0000000..f0803d4 --- /dev/null +++ b/inc/MicroBitLEDService.h @@ -0,0 +1,59 @@ +#ifndef MICROBIT_LED_SERVICE_H +#define MICROBIT_LED_SERVICE_H + +#include "MicroBit.h" + +// UUIDs for our service and characteristics +extern const uint8_t MicroBitLEDServiceUUID[]; +extern const uint8_t MicroBitLEDServiceMatrixUUID[]; +extern const uint8_t MicroBitLEDServiceTextUUID[]; +extern const uint8_t MicroBitLEDServiceScrollingSpeedUUID[]; + + +/** + * Class definition for a MicroBit BLE Event Service. + * Provides a _ble gateway onto the MicroBit Message Bus. + */ +class MicroBitLEDService +{ + public: + + /** + * Constructor. + * Create a representation of the LEDService + * @param BLE The instance of a BLE device that we're running on. + */ + MicroBitLEDService(BLEDevice &_ble); + + /** + * Callback. Invoked when any of our attributes are written via BLE. + */ + void onDataWritten(const GattWriteCallbackParams *params); + + /** + * Callback. Invoked when any of our attributes are read via BLE. + */ + void onDataRead(GattReadAuthCallbackParams *params); + + private: + + // Bluetooth stack we're running on. + BLEDevice &ble; + + // memory for our 8 bit control characteristics. + uint32_t matrixCharacteristicBuffer; + uint8_t textCharacteristicBuffer[MICROBIT_BLE_MAXIMUM_SCROLLTEXT]; + uint8_t scrollingSpeedCharacteristicBuffer; + + // Handles to access each characteristic when they are held by Soft Device. + GattAttribute::Handle_t matrixCharacteristicHandle; + GattAttribute::Handle_t textCharacteristicHandle; + GattAttribute::Handle_t scrollingSpeedCharacteristicHandle; + + // We hold a copy of the GattCharacteristic, as mbed's BLE API requires this to provide read callbacks (pity!). + GattCharacteristic matrixCharacteristic; +}; + + +#endif + diff --git a/source/ble-services/MicroBitLEDService.cpp b/source/ble-services/MicroBitLEDService.cpp new file mode 100644 index 0000000..ae8c301 --- /dev/null +++ b/source/ble-services/MicroBitLEDService.cpp @@ -0,0 +1,135 @@ +/** + * Class definition for the custom MicroBit LED Service. + * Provides a BLE service to remotely read and write the state of the LED display. + */ + +#include "MicroBit.h" +#include "ble/UUID.h" + +#include "MicroBitLEDService.h" + +/** + * Constructor. + * Create a representation of the LEDService + * @param _ble The instance of a BLE device that we're running on. + */ +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) +{ + // Create the data structures that represent each of our characteristics in Soft Device. + GattCharacteristic textCharacteristic(MicroBitLEDServiceTextUUID, (uint8_t *)textCharacteristicBuffer, 0, MICROBIT_BLE_MAXIMUM_SCROLLTEXT, + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); + + GattCharacteristic scrollingSpeedCharacteristic(MicroBitLEDServiceScrollingSpeedUUID, (uint8_t *)&scrollingSpeedCharacteristicBuffer, 0, + sizeof(scrollingSpeedCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); + + // Initialise our characteristic values. + matrixCharacteristicBuffer = 0; + textCharacteristicBuffer[0] = 0; + scrollingSpeedCharacteristicBuffer = MICROBIT_DEFAULT_SCROLL_SPEED; + + matrixCharacteristic.setReadAuthorizationCallback(this, &MicroBitLEDService::onDataRead); + + + GattCharacteristic *characteristics[] = {&matrixCharacteristic, &textCharacteristic, &scrollingSpeedCharacteristic}; + GattService service(MicroBitLEDServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *)); + + ble.addService(service); + + matrixCharacteristicHandle = matrixCharacteristic.getValueHandle(); + textCharacteristicHandle = textCharacteristic.getValueHandle(); + scrollingSpeedCharacteristicHandle = scrollingSpeedCharacteristic.getValueHandle(); + + ble.updateCharacteristicValue(scrollingSpeedCharacteristicHandle, (const uint8_t *)&scrollingSpeedCharacteristicBuffer, sizeof(scrollingSpeedCharacteristicBuffer)); + ble.updateCharacteristicValue(matrixCharacteristicHandle, (const uint8_t *)&matrixCharacteristicBuffer, sizeof(matrixCharacteristicBuffer)); + + ble.onDataWritten(this, &MicroBitLEDService::onDataWritten); + + +} + + +/** + * Callback. Invoked when any of our attributes are written via BLE. + */ +void MicroBitLEDService::onDataWritten(const GattWriteCallbackParams *params) +{ + if (params->handle == matrixCharacteristicHandle && params->len >= 4) + { + uint32_t d = *((uint32_t *)params->data); + uint32_t mask = 0x01; + + for (int x=0; x<5; x++) + { + for (int y=0; y<5; y++) + { + uBit.display.image.setPixelValue(x, y, (d & mask) ? 255 : 0); + mask = mask << 1; + } + } + } + + else if (params->handle == textCharacteristicHandle) + { + // Create a ManagedString representation from the UTF8 data. + // We do this explicitly to control the length (in case the string is not NULL terminated!) + ManagedString s((char *)params->data, params->len); + + // Start the string scrolling and we're done. + uBit.display.scrollAsync(s, (int) scrollingSpeedCharacteristicBuffer); + } + + else if (params->handle == scrollingSpeedCharacteristicHandle && params->len >= sizeof(scrollingSpeedCharacteristicBuffer)) + { + // Read the speed requested, and store it locally. + // We use this as the speed for all scroll operations subsquently initiated from BLE. + scrollingSpeedCharacteristicBuffer = *((uint8_t *)params->data); + } +} + +/** + * Callback. Invoked when any of our attributes are read via BLE. + */ +void MicroBitLEDService::onDataRead(GattReadAuthCallbackParams *params) +{ + if (params->handle == matrixCharacteristicHandle) + { + uint32_t mask = 0x01; + + matrixCharacteristicBuffer = 0; + + for (int x=0; x<5; x++) + { + for (int y=0; y<5; y++) + { + if (uBit.display.image.getPixelValue(x, y)) + matrixCharacteristicBuffer |= mask; + + mask = mask << 1; + } + } + + ble.updateCharacteristicValue(matrixCharacteristicHandle, (const uint8_t *)&matrixCharacteristicBuffer, sizeof(matrixCharacteristicBuffer)); + } +} + + +const uint8_t MicroBitLEDServiceUUID[] = { + 0xe9,0x5d,0xd9,0x1d,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 +}; + +const uint8_t MicroBitLEDServiceMatrixUUID[] = { + 0xe9,0x5d,0x7b,0x77,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 +}; + +const uint8_t MicroBitLEDServiceTextUUID[] = { + 0xe9,0x5d,0x93,0xee,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 +}; + +const uint8_t MicroBitLEDServiceScrollingSpeedUUID[] = { + 0xe9,0x5d,0x0d,0x2d,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 +}; + +