From 383b8b18b3e6806190845645eea98e3f7af819e7 Mon Sep 17 00:00:00 2001 From: Martin Woolley Date: Wed, 31 Aug 2016 12:09:20 +0100 Subject: [PATCH 1/3] Added PWM Control characteristic to the IO Pin Service --- inc/bluetooth/MicroBitIOPinService.h | 15 +++++++- source/bluetooth/MicroBitIOPinService.cpp | 46 ++++++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/inc/bluetooth/MicroBitIOPinService.h b/inc/bluetooth/MicroBitIOPinService.h index f130e4e..a04681f 100644 --- a/inc/bluetooth/MicroBitIOPinService.h +++ b/inc/bluetooth/MicroBitIOPinService.h @@ -32,11 +32,13 @@ DEALINGS IN THE SOFTWARE. #define MICROBIT_IO_PIN_SERVICE_PINCOUNT 19 #define MICROBIT_IO_PIN_SERVICE_DATA_SIZE 10 +#define MICROBIT_PWM_PIN_SERVICE_DATA_SIZE 3 // UUIDs for our service and characteristics extern const uint8_t MicroBitIOPinServiceUUID[]; extern const uint8_t MicroBitIOPinServiceADConfigurationUUID[]; extern const uint8_t MicroBitIOPinServiceIOConfigurationUUID[]; +extern const uint8_t MicroBitIOPinServicePWMControlUUID[]; extern const uint8_t MicroBitIOPinServiceDataUUID[]; extern MicroBitPin * const MicroBitIOPins[]; @@ -49,6 +51,16 @@ struct IOData uint8_t value; }; +/** + * PWM control type definition, as used to set PWM properties of one of more conpatible pins over BLE + */ +struct IOPWMData +{ + uint8_t pin; + uint16_t value; + uint32_t period; +} __attribute__((packed)); + /** * Class definition for the custom MicroBit IOPin Service. * Provides a BLE service to remotely read the state of the I/O Pin, and configure its behaviour. @@ -128,6 +140,7 @@ class MicroBitIOPinService : public MicroBitComponent // memory for our 8 bit control characteristics. uint32_t ioPinServiceADCharacteristicBuffer; uint32_t ioPinServiceIOCharacteristicBuffer; + IOPWMData ioPinServicePWMCharacteristicBuffer[MICROBIT_PWM_PIN_SERVICE_DATA_SIZE]; IOData ioPinServiceDataCharacteristicBuffer[MICROBIT_IO_PIN_SERVICE_DATA_SIZE]; // Historic information about our pin data data. @@ -136,8 +149,8 @@ class MicroBitIOPinService : public MicroBitComponent // Handles to access each characteristic when they are held by Soft Device. GattAttribute::Handle_t ioPinServiceADCharacteristicHandle; GattAttribute::Handle_t ioPinServiceIOCharacteristicHandle; + GattAttribute::Handle_t ioPinServicePWMCharacteristicHandle; GattCharacteristic *ioPinServiceDataCharacteristic; }; - #endif diff --git a/source/bluetooth/MicroBitIOPinService.cpp b/source/bluetooth/MicroBitIOPinService.cpp index e336a89..5c616f1 100644 --- a/source/bluetooth/MicroBitIOPinService.cpp +++ b/source/bluetooth/MicroBitIOPinService.cpp @@ -49,6 +49,9 @@ MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble, MicroBitIO &_io) : // Create the IO characteristic, that defines whether each pin is treated as input or output GattCharacteristic ioPinServiceIOCharacteristic(MicroBitIOPinServiceIOConfigurationUUID, (uint8_t *)&ioPinServiceIOCharacteristicBuffer, 0, sizeof(ioPinServiceIOCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); + // Create the PWM characteristic, that allows up to 3 compatible pins to be used for PWM + GattCharacteristic ioPinServicePWMCharacteristic(MicroBitIOPinServicePWMControlUUID, (uint8_t *)&ioPinServicePWMCharacteristicBuffer, 0, sizeof(ioPinServicePWMCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); + // Create the Data characteristic, that allows the actual read and write operations. ioPinServiceDataCharacteristic = new GattCharacteristic(MicroBitIOPinServiceDataUUID, (uint8_t *)ioPinServiceDataCharacteristicBuffer, 0, sizeof(ioPinServiceDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); @@ -57,22 +60,26 @@ MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble, MicroBitIO &_io) : ioPinServiceADCharacteristicBuffer = 0; ioPinServiceIOCharacteristicBuffer = 0; memset(ioPinServiceIOData, 0, sizeof(ioPinServiceIOData)); + memset(ioPinServicePWMCharacteristicBuffer, 0, sizeof(ioPinServicePWMCharacteristicBuffer)); // Set default security requirements ioPinServiceADCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL); ioPinServiceIOCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL); + ioPinServicePWMCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL); ioPinServiceDataCharacteristic->requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL); - GattCharacteristic *characteristics[] = {&ioPinServiceADCharacteristic, &ioPinServiceIOCharacteristic, ioPinServiceDataCharacteristic}; + GattCharacteristic *characteristics[] = {&ioPinServiceADCharacteristic, &ioPinServiceIOCharacteristic, &ioPinServicePWMCharacteristic, ioPinServiceDataCharacteristic}; GattService service(MicroBitIOPinServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *)); ble.addService(service); ioPinServiceADCharacteristicHandle = ioPinServiceADCharacteristic.getValueHandle(); ioPinServiceIOCharacteristicHandle = ioPinServiceIOCharacteristic.getValueHandle(); + ioPinServicePWMCharacteristicHandle = ioPinServicePWMCharacteristic.getValueHandle(); ble.gattServer().write(ioPinServiceADCharacteristicHandle, (const uint8_t *)&ioPinServiceADCharacteristicBuffer, sizeof(ioPinServiceADCharacteristicBuffer)); ble.gattServer().write(ioPinServiceIOCharacteristicHandle, (const uint8_t *)&ioPinServiceIOCharacteristicBuffer, sizeof(ioPinServiceIOCharacteristicBuffer)); + ble.gattServer().write(ioPinServicePWMCharacteristicHandle, (const uint8_t *)&ioPinServicePWMCharacteristicBuffer, sizeof(ioPinServicePWMCharacteristicBuffer)); ble.onDataWritten(this, &MicroBitIOPinService::onDataWritten); fiber_add_idle_component(this); @@ -127,6 +134,8 @@ int MicroBitIOPinService::isOutput(int i) */ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params) { + SERIAL_DEBUG->printf("params->len: %d",params->len); + // Check for writes to the IO configuration characteristic if (params->handle == ioPinServiceIOCharacteristicHandle && params->len >= sizeof(ioPinServiceIOCharacteristicBuffer)) { @@ -171,13 +180,42 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params) } } + // Check for writes to the PWM Control characteristic + if (params->handle == ioPinServicePWMCharacteristicHandle) + { + uint16_t len = params->len; + IOPWMData *pwm_data = (IOPWMData *)params->data; + + //validate - len must be a multiple of 7 and greater than 0 + if (len == 0) { + SERIAL_DEBUG->printf("ERROR - zero length PWM Control field: %d",len); + return; + } + + bool is_valid_length = len % 7 == 0; + if (is_valid_length) { + uint8_t field_count = len / 7; + for (int i=0;iprintf("ERROR - invalid PWM Control field length: %d",len); + return; + } + } + if (params->handle == ioPinServiceDataCharacteristic->getValueHandle()) { // We have some pin data to change... uint16_t len = params->len; IOData *data = (IOData *)params->data; - // There may be multiple write operaitons... take each in turn and update the pin values + // There may be multiple write operations... take each in turn and update the pin values while (len >= sizeof(IOData)) { if (isOutput(data->pin)) @@ -301,6 +339,10 @@ const uint8_t MicroBitIOPinServiceADConfigurationUUID[] = { 0xe9,0x5d,0x58,0x99,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 }; +const uint8_t MicroBitIOPinServicePWMControlUUID[] = { + 0xe9,0x5d,0xd8,0x22,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 +}; + const uint8_t MicroBitIOPinServiceDataUUID[] = { 0xe9,0x5d,0x8d,0x00,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8 }; From 6c4fa882a3cc41bb9b4f7e5a7a4ed31cd2dc0310 Mon Sep 17 00:00:00 2001 From: Martin Woolley Date: Wed, 31 Aug 2016 12:11:26 +0100 Subject: [PATCH 2/3] Added PWM Control characteristic to the IO Pin Service --- inc/bluetooth/MicroBitIOPinService.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/bluetooth/MicroBitIOPinService.h b/inc/bluetooth/MicroBitIOPinService.h index a04681f..623efef 100644 --- a/inc/bluetooth/MicroBitIOPinService.h +++ b/inc/bluetooth/MicroBitIOPinService.h @@ -32,7 +32,7 @@ DEALINGS IN THE SOFTWARE. #define MICROBIT_IO_PIN_SERVICE_PINCOUNT 19 #define MICROBIT_IO_PIN_SERVICE_DATA_SIZE 10 -#define MICROBIT_PWM_PIN_SERVICE_DATA_SIZE 3 +#define MICROBIT_PWM_PIN_SERVICE_DATA_SIZE 2 // UUIDs for our service and characteristics extern const uint8_t MicroBitIOPinServiceUUID[]; From b73be32eeb09b3a1139946fc47b921751144762b Mon Sep 17 00:00:00 2001 From: Martin Woolley Date: Thu, 1 Sep 2016 06:04:01 +0100 Subject: [PATCH 3/3] removed serial debug output --- source/bluetooth/MicroBitIOPinService.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/bluetooth/MicroBitIOPinService.cpp b/source/bluetooth/MicroBitIOPinService.cpp index 5c616f1..765cf0f 100644 --- a/source/bluetooth/MicroBitIOPinService.cpp +++ b/source/bluetooth/MicroBitIOPinService.cpp @@ -134,8 +134,6 @@ int MicroBitIOPinService::isOutput(int i) */ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params) { - SERIAL_DEBUG->printf("params->len: %d",params->len); - // Check for writes to the IO configuration characteristic if (params->handle == ioPinServiceIOCharacteristicHandle && params->len >= sizeof(ioPinServiceIOCharacteristicBuffer)) { @@ -188,7 +186,6 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params) //validate - len must be a multiple of 7 and greater than 0 if (len == 0) { - SERIAL_DEBUG->printf("ERROR - zero length PWM Control field: %d",len); return; } @@ -204,7 +201,6 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params) } } else { // there's no way to return an error response via the current mbed BLE API :-( See https://github.com/ARMmbed/ble/issues/181 - SERIAL_DEBUG->printf("ERROR - invalid PWM Control field length: %d",len); return; } }