Basic demo that shows how to control a Zumo shield using ST X-NUCLEO-IDB04A1 BlueTooth Low energy shield.

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 ZumoShield mbed

ST BLE shield: https://developer.mbed.org/components/X-NUCLEO-IDB04A1/

/media/uploads/bcostm/nucleo-ble-shield.jpg

Zumo shield: https://www.pololu.com/category/169/zumo-robot-for-arduino

/media/uploads/bcostm/zumo.jpg

Android Application: TBD

Committer:
bcostm
Date:
Mon Oct 12 11:35:56 2015 +0000
Revision:
1:f9ed96482986
Parent:
0:901651f381c9
Initial version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bcostm 0:901651f381c9 1 /* mbed Microcontroller Library
bcostm 0:901651f381c9 2 * Copyright (c) 2006-2013 ARM Limited
bcostm 0:901651f381c9 3 *
bcostm 0:901651f381c9 4 * Licensed under the Apache License, Version 2.0 (the "License");
bcostm 0:901651f381c9 5 * you may not use this file except in compliance with the License.
bcostm 0:901651f381c9 6 * You may obtain a copy of the License at
bcostm 0:901651f381c9 7 *
bcostm 0:901651f381c9 8 * http://www.apache.org/licenses/LICENSE-2.0
bcostm 0:901651f381c9 9 *
bcostm 0:901651f381c9 10 * Unless required by applicable law or agreed to in writing, software
bcostm 0:901651f381c9 11 * distributed under the License is distributed on an "AS IS" BASIS,
bcostm 0:901651f381c9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bcostm 0:901651f381c9 13 * See the License for the specific language governing permissions and
bcostm 0:901651f381c9 14 * limitations under the License.
bcostm 0:901651f381c9 15 */
bcostm 0:901651f381c9 16
bcostm 0:901651f381c9 17 #ifndef __SAMPLE_SERVICE_H__
bcostm 0:901651f381c9 18 #define __SAMPLE_SERVICE_H__
bcostm 0:901651f381c9 19
bcostm 0:901651f381c9 20 #include "mbed.h"
bcostm 0:901651f381c9 21 #include "Stream.h"
bcostm 0:901651f381c9 22
bcostm 0:901651f381c9 23 #include "ble/UUID.h"
bcostm 0:901651f381c9 24 #include "ble/BLE.h"
bcostm 0:901651f381c9 25 #include "Utils.h"
bcostm 0:901651f381c9 26
bcostm 0:901651f381c9 27 //extern DigitalOut led1;
bcostm 0:901651f381c9 28
bcostm 0:901651f381c9 29 extern const uint8_t SampleServiceUUID[UUID::LENGTH_OF_LONG_UUID];
bcostm 0:901651f381c9 30 extern const uint16_t SampleServiceShortUUID;
bcostm 0:901651f381c9 31
bcostm 0:901651f381c9 32 extern const uint8_t TXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
bcostm 0:901651f381c9 33 extern const uint8_t RXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
bcostm 0:901651f381c9 34
bcostm 0:901651f381c9 35 /**
bcostm 0:901651f381c9 36 * @class SampleService
bcostm 0:901651f381c9 37 * @brief BLE Service to enable ... over BLE
bcostm 0:901651f381c9 38 */
bcostm 0:901651f381c9 39 class SampleService {
bcostm 0:901651f381c9 40 public:
bcostm 0:901651f381c9 41 /**< Maximum length of data (in bytes) that can be transmitted by the Sample service module to the peer. */
bcostm 0:901651f381c9 42 static const unsigned BLE_SAMPLE_SERVICE_MAX_DATA_LEN = (BLE_GATT_MTU_SIZE_DEFAULT - 3);
bcostm 0:901651f381c9 43
bcostm 0:901651f381c9 44 public:
bcostm 0:901651f381c9 45
bcostm 0:901651f381c9 46 /**
bcostm 0:901651f381c9 47 * @param[ref] ble
bcostm 0:901651f381c9 48 * BLE object for the underlying controller.
bcostm 0:901651f381c9 49 */
bcostm 0:901651f381c9 50 SampleService(BLE &_ble, void (*appCbk)(const uint8_t*, uint16_t)) :
bcostm 0:901651f381c9 51 ble(_ble),
bcostm 0:901651f381c9 52 receiveBuffer(),
bcostm 0:901651f381c9 53 sendBuffer(),
bcostm 0:901651f381c9 54 sendBufferIndex(0),
bcostm 0:901651f381c9 55 numBytesReceived(0),
bcostm 0:901651f381c9 56 receiveBufferIndex(0),
bcostm 0:901651f381c9 57 txCharacteristic(TXCharacteristicUUID, sendBuffer, 1, BLE_SAMPLE_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
bcostm 0:901651f381c9 58 rxCharacteristic(RXCharacteristicUUID, receiveBuffer, 1, BLE_SAMPLE_SERVICE_MAX_DATA_LEN,
bcostm 0:901651f381c9 59 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE) {
bcostm 0:901651f381c9 60 GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
bcostm 0:901651f381c9 61 GattService sampleService(SampleServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
bcostm 0:901651f381c9 62
bcostm 0:901651f381c9 63 appCallback = appCbk;
bcostm 0:901651f381c9 64
bcostm 0:901651f381c9 65 ble.addService(sampleService);
bcostm 0:901651f381c9 66 ble.onDataWritten(this, &SampleService::onDataWritten);
bcostm 0:901651f381c9 67 }
bcostm 0:901651f381c9 68
bcostm 0:901651f381c9 69 /**
bcostm 0:901651f381c9 70 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
bcostm 0:901651f381c9 71 */
bcostm 0:901651f381c9 72 uint16_t getTXCharacteristicHandle() {
bcostm 0:901651f381c9 73 return txCharacteristic.getValueAttribute().getHandle();
bcostm 0:901651f381c9 74 }
bcostm 0:901651f381c9 75
bcostm 0:901651f381c9 76 /**
bcostm 0:901651f381c9 77 * Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
bcostm 0:901651f381c9 78 */
bcostm 0:901651f381c9 79 uint16_t getRXCharacteristicHandle() {
bcostm 0:901651f381c9 80 return rxCharacteristic.getValueAttribute().getHandle();
bcostm 0:901651f381c9 81 }
bcostm 0:901651f381c9 82
bcostm 0:901651f381c9 83 /**
bcostm 0:901651f381c9 84 * We attempt to collect bytes before pushing them to the UART RX
bcostm 0:901651f381c9 85 * characteristic--writing to the RX characteristic will then generate
bcostm 0:901651f381c9 86 * notifications for the client. Updates made in quick succession to a
bcostm 0:901651f381c9 87 * notification-generating characteristic will result in data being buffered
bcostm 0:901651f381c9 88 * in the bluetooth stack as notifications are sent out. The stack will have
bcostm 0:901651f381c9 89 * its limits for this buffering; typically a small number under 10.
bcostm 0:901651f381c9 90 * Collecting data into the sendBuffer buffer helps mitigate the rate of
bcostm 0:901651f381c9 91 * updates. But we shouldn't buffer a large amount of data before updating
bcostm 0:901651f381c9 92 * the characteristic otherwise the client will need to turn around and make
bcostm 0:901651f381c9 93 * a long read request; this is because notifications include only the first
bcostm 0:901651f381c9 94 * 20 bytes of the updated data.
bcostm 0:901651f381c9 95 *
bcostm 0:901651f381c9 96 * @param buffer The received update
bcostm 0:901651f381c9 97 * @param length Amount of characters to be appended.
bcostm 0:901651f381c9 98 * @return Amount of characters appended to the rxCharacteristic.
bcostm 0:901651f381c9 99 */
bcostm 0:901651f381c9 100 size_t write(const void *_buffer, size_t length) {
bcostm 0:901651f381c9 101 size_t origLength = length;
bcostm 0:901651f381c9 102 const uint8_t *buffer = static_cast<const uint8_t *>(_buffer);
bcostm 0:901651f381c9 103
bcostm 0:901651f381c9 104 if (ble.getGapState().connected) {
bcostm 0:901651f381c9 105 unsigned bufferIndex = 0;
bcostm 0:901651f381c9 106 while (length) {
bcostm 0:901651f381c9 107 unsigned bytesRemainingInSendBuffer = BLE_SAMPLE_SERVICE_MAX_DATA_LEN - sendBufferIndex;
bcostm 0:901651f381c9 108 unsigned bytesToCopy = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
bcostm 0:901651f381c9 109
bcostm 0:901651f381c9 110 /* copy bytes into sendBuffer */
bcostm 0:901651f381c9 111 memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
bcostm 0:901651f381c9 112 length -= bytesToCopy;
bcostm 0:901651f381c9 113 sendBufferIndex += bytesToCopy;
bcostm 0:901651f381c9 114 bufferIndex += bytesToCopy;
bcostm 0:901651f381c9 115
bcostm 0:901651f381c9 116 /* have we collected enough? */
bcostm 0:901651f381c9 117 if ((sendBufferIndex == BLE_SAMPLE_SERVICE_MAX_DATA_LEN) ||
bcostm 0:901651f381c9 118 // (sendBuffer[sendBufferIndex - 1] == '\r') ||
bcostm 0:901651f381c9 119 (sendBuffer[sendBufferIndex - 1] == '\n')) {
bcostm 0:901651f381c9 120 ble.gattServer().write(getTXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
bcostm 0:901651f381c9 121 sendBufferIndex = 0;
bcostm 0:901651f381c9 122 }
bcostm 0:901651f381c9 123 }
bcostm 0:901651f381c9 124 }
bcostm 0:901651f381c9 125
bcostm 0:901651f381c9 126 return origLength;
bcostm 0:901651f381c9 127 }
bcostm 0:901651f381c9 128
bcostm 0:901651f381c9 129 /**
bcostm 0:901651f381c9 130 * Helper function to write out strings.
bcostm 0:901651f381c9 131 * @param str The received string.
bcostm 0:901651f381c9 132 * @return Amount of characters appended to the rxCharacteristic.
bcostm 0:901651f381c9 133 */
bcostm 0:901651f381c9 134 size_t writeString(const char *str) {
bcostm 0:901651f381c9 135 return write(str, strlen(str));
bcostm 0:901651f381c9 136 }
bcostm 0:901651f381c9 137
bcostm 0:901651f381c9 138 /**
bcostm 0:901651f381c9 139 * Override for Stream::_putc()
bcostm 0:901651f381c9 140 * @param c
bcostm 0:901651f381c9 141 * This function writes the character c, cast to an unsigned char, to stream.
bcostm 0:901651f381c9 142 * @return
bcostm 0:901651f381c9 143 * The character written as an unsigned char cast to an int or EOF on error.
bcostm 0:901651f381c9 144 */
bcostm 0:901651f381c9 145 int _putc(int c) {
bcostm 0:901651f381c9 146 return (write(&c, 1) == 1) ? 1 : EOF;
bcostm 0:901651f381c9 147 }
bcostm 0:901651f381c9 148
bcostm 0:901651f381c9 149 /**
bcostm 0:901651f381c9 150 * Override for Stream::_getc()
bcostm 0:901651f381c9 151 * @return
bcostm 0:901651f381c9 152 * The character read.
bcostm 0:901651f381c9 153 */
bcostm 0:901651f381c9 154 int _getc() {
bcostm 0:901651f381c9 155 if (receiveBufferIndex == numBytesReceived) {
bcostm 0:901651f381c9 156 return EOF;
bcostm 0:901651f381c9 157 }
bcostm 0:901651f381c9 158
bcostm 0:901651f381c9 159 return receiveBuffer[receiveBufferIndex++];
bcostm 0:901651f381c9 160 }
bcostm 0:901651f381c9 161
bcostm 0:901651f381c9 162 protected:
bcostm 0:901651f381c9 163 /**
bcostm 0:901651f381c9 164 * This callback allows the UART service to receive updates to the
bcostm 0:901651f381c9 165 * txCharacteristic. The application should forward the call to this
bcostm 0:901651f381c9 166 * function from the global onDataWritten() callback handler; or if that's
bcostm 0:901651f381c9 167 * not used, this method can be used as a callback directly.
bcostm 0:901651f381c9 168 */
bcostm 0:901651f381c9 169 void onDataWritten(const GattWriteCallbackParams *params) {
bcostm 0:901651f381c9 170 if (params->handle == getRXCharacteristicHandle()) {
bcostm 0:901651f381c9 171 uint16_t bytesRead = params->len;
bcostm 0:901651f381c9 172 if (bytesRead <= BLE_SAMPLE_SERVICE_MAX_DATA_LEN) {
bcostm 0:901651f381c9 173 numBytesReceived = bytesRead;
bcostm 0:901651f381c9 174 receiveBufferIndex = 0;
bcostm 0:901651f381c9 175 memcpy(receiveBuffer, params->data, numBytesReceived);
bcostm 0:901651f381c9 176 if(appCallback) {
bcostm 0:901651f381c9 177 appCallback(params->data, params->len);
bcostm 0:901651f381c9 178 }
bcostm 0:901651f381c9 179 }
bcostm 0:901651f381c9 180 }
bcostm 0:901651f381c9 181 }
bcostm 0:901651f381c9 182
bcostm 0:901651f381c9 183 protected:
bcostm 0:901651f381c9 184 BLE &ble;
bcostm 0:901651f381c9 185 void (*appCallback)(const uint8_t*, uint16_t);
bcostm 0:901651f381c9 186
bcostm 0:901651f381c9 187 uint8_t receiveBuffer[BLE_SAMPLE_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
bcostm 0:901651f381c9 188 * inbound data before forwarding it to the
bcostm 0:901651f381c9 189 * application. */
bcostm 0:901651f381c9 190
bcostm 0:901651f381c9 191 uint8_t sendBuffer[BLE_SAMPLE_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which outbound data is
bcostm 0:901651f381c9 192 * accumulated before being pushed to the
bcostm 0:901651f381c9 193 * rxCharacteristic. */
bcostm 0:901651f381c9 194 uint8_t sendBufferIndex;
bcostm 0:901651f381c9 195 uint8_t numBytesReceived;
bcostm 0:901651f381c9 196 uint8_t receiveBufferIndex;
bcostm 0:901651f381c9 197
bcostm 0:901651f381c9 198 GattCharacteristic txCharacteristic; /**< From the point of view of the external client, this is the characteristic
bcostm 0:901651f381c9 199 * they'd write into in order to communicate with this application. */
bcostm 0:901651f381c9 200 GattCharacteristic rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
bcostm 0:901651f381c9 201 * they'd read from in order to receive the bytes transmitted by this
bcostm 0:901651f381c9 202 * application. */
bcostm 0:901651f381c9 203 };
bcostm 0:901651f381c9 204
bcostm 0:901651f381c9 205 #endif /* #ifndef __SAMPLE_SERVICE_H__*/