To get started with Seeed Tiny BLE, include detecting motion, button and battery level.

Dependencies:   BLE_API eMPL_MPU6050 mbed nRF51822

Committer:
yihui
Date:
Wed Apr 22 07:47:17 2015 +0000
Revision:
1:fc2f9d636751
update libraries; ; delete nRF51822/nordic-sdk/components/gpiote/app_gpiote.c to solve GPIOTE_IRQHandler multiply defined issue. temperarily change nRF51822 library to folder

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 1:fc2f9d636751 1 /* mbed Microcontroller Library
yihui 1:fc2f9d636751 2 * Copyright (c) 2006-2013 ARM Limited
yihui 1:fc2f9d636751 3 *
yihui 1:fc2f9d636751 4 * Licensed under the Apache License, Version 2.0 (the "License");
yihui 1:fc2f9d636751 5 * you may not use this file except in compliance with the License.
yihui 1:fc2f9d636751 6 * You may obtain a copy of the License at
yihui 1:fc2f9d636751 7 *
yihui 1:fc2f9d636751 8 * http://www.apache.org/licenses/LICENSE-2.0
yihui 1:fc2f9d636751 9 *
yihui 1:fc2f9d636751 10 * Unless required by applicable law or agreed to in writing, software
yihui 1:fc2f9d636751 11 * distributed under the License is distributed on an "AS IS" BASIS,
yihui 1:fc2f9d636751 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
yihui 1:fc2f9d636751 13 * See the License for the specific language governing permissions and
yihui 1:fc2f9d636751 14 * limitations under the License.
yihui 1:fc2f9d636751 15 */
yihui 1:fc2f9d636751 16
yihui 1:fc2f9d636751 17 #include "custom_helper.h"
yihui 1:fc2f9d636751 18
yihui 1:fc2f9d636751 19 /*
yihui 1:fc2f9d636751 20 * The current version of the soft-device doesn't handle duplicate 128-bit UUIDs
yihui 1:fc2f9d636751 21 * very well. It is therefore necessary to filter away duplicates before
yihui 1:fc2f9d636751 22 * passing long UUIDs to sd_ble_uuid_vs_add(). The following types and data
yihui 1:fc2f9d636751 23 * structures involved in maintaining a local cache of 128-bit UUIDs.
yihui 1:fc2f9d636751 24 */
yihui 1:fc2f9d636751 25 typedef struct {
yihui 1:fc2f9d636751 26 LongUUIDBytes_t uuid;
yihui 1:fc2f9d636751 27 uint8_t type;
yihui 1:fc2f9d636751 28 } converted_uuid_table_entry_t;
yihui 1:fc2f9d636751 29 static const unsigned UUID_TABLE_MAX_ENTRIES = 8; /* This is the maximum number of 128-bit UUIDs with distinct bases that
yihui 1:fc2f9d636751 30 * we expect to be in use; increase this limit if needed. */
yihui 1:fc2f9d636751 31 static unsigned uuidTableEntries = 0; /* current usage of the table */
yihui 1:fc2f9d636751 32 converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
yihui 1:fc2f9d636751 33
yihui 1:fc2f9d636751 34 /**
yihui 1:fc2f9d636751 35 * lookup the cache of previously converted 128-bit UUIDs to find a type value.
yihui 1:fc2f9d636751 36 * @param uuid base 128-bit UUID
yihui 1:fc2f9d636751 37 * @param recoveredType the type field of the 3-byte nRF's uuid.
yihui 1:fc2f9d636751 38 * @return true if a match is found.
yihui 1:fc2f9d636751 39 */
yihui 1:fc2f9d636751 40 static bool
yihui 1:fc2f9d636751 41 lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType)
yihui 1:fc2f9d636751 42 {
yihui 1:fc2f9d636751 43 unsigned i;
yihui 1:fc2f9d636751 44 for (i = 0; i < uuidTableEntries; i++) {
yihui 1:fc2f9d636751 45 unsigned byteIndex;
yihui 1:fc2f9d636751 46 for (byteIndex = 0; byteIndex < LENGTH_OF_LONG_UUID; byteIndex++) {
yihui 1:fc2f9d636751 47 /* Skip bytes 2 and 3, because they contain the shortUUID (16-bit) version of the
yihui 1:fc2f9d636751 48 * long UUID; and we're comparing against the remainder. */
yihui 1:fc2f9d636751 49 if ((byteIndex == 2) || (byteIndex == 3)) {
yihui 1:fc2f9d636751 50 continue;
yihui 1:fc2f9d636751 51 }
yihui 1:fc2f9d636751 52
yihui 1:fc2f9d636751 53 if (convertedUUIDTable[i].uuid[byteIndex] != uuid[byteIndex]) {
yihui 1:fc2f9d636751 54 break;
yihui 1:fc2f9d636751 55 }
yihui 1:fc2f9d636751 56 }
yihui 1:fc2f9d636751 57
yihui 1:fc2f9d636751 58 if (byteIndex == LENGTH_OF_LONG_UUID) {
yihui 1:fc2f9d636751 59 *recoveredType = convertedUUIDTable[i].type;
yihui 1:fc2f9d636751 60 return true;
yihui 1:fc2f9d636751 61 }
yihui 1:fc2f9d636751 62 }
yihui 1:fc2f9d636751 63
yihui 1:fc2f9d636751 64 return false;
yihui 1:fc2f9d636751 65 }
yihui 1:fc2f9d636751 66
yihui 1:fc2f9d636751 67 static void
yihui 1:fc2f9d636751 68 addToConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t type)
yihui 1:fc2f9d636751 69 {
yihui 1:fc2f9d636751 70 if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) {
yihui 1:fc2f9d636751 71 return; /* recovery needed; or at least the user should be warned about this fact.*/
yihui 1:fc2f9d636751 72 }
yihui 1:fc2f9d636751 73
yihui 1:fc2f9d636751 74 memcpy(convertedUUIDTable[uuidTableEntries].uuid, uuid, LENGTH_OF_LONG_UUID);
yihui 1:fc2f9d636751 75 convertedUUIDTable[uuidTableEntries].uuid[2] = 0;
yihui 1:fc2f9d636751 76 convertedUUIDTable[uuidTableEntries].uuid[3] = 0;
yihui 1:fc2f9d636751 77 convertedUUIDTable[uuidTableEntries].type = type;
yihui 1:fc2f9d636751 78 uuidTableEntries++;
yihui 1:fc2f9d636751 79 }
yihui 1:fc2f9d636751 80
yihui 1:fc2f9d636751 81 /**
yihui 1:fc2f9d636751 82 * The nRF transport has its own 3-byte representation of a UUID. If the user-
yihui 1:fc2f9d636751 83 * specified UUID is 128-bits wide, then the UUID base needs to be added to the
yihui 1:fc2f9d636751 84 * soft-device and converted to a 3-byte handle before being used further. This
yihui 1:fc2f9d636751 85 * function is responsible for this translation of user-specified UUIDs into
yihui 1:fc2f9d636751 86 * nRF's representation.
yihui 1:fc2f9d636751 87 *
yihui 1:fc2f9d636751 88 * @param[in] uuid
yihui 1:fc2f9d636751 89 * user-specified UUID
yihui 1:fc2f9d636751 90 * @return nRF
yihui 1:fc2f9d636751 91 * 3-byte UUID (containing a type and 16-bit UUID) representation
yihui 1:fc2f9d636751 92 * to be used with SVC calls.
yihui 1:fc2f9d636751 93 */
yihui 1:fc2f9d636751 94 ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid)
yihui 1:fc2f9d636751 95 {
yihui 1:fc2f9d636751 96 ble_uuid_t nordicUUID;
yihui 1:fc2f9d636751 97 nordicUUID.uuid = uuid.getShortUUID();
yihui 1:fc2f9d636751 98 nordicUUID.type = BLE_UUID_TYPE_UNKNOWN; /* to be set below */
yihui 1:fc2f9d636751 99
yihui 1:fc2f9d636751 100 if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) {
yihui 1:fc2f9d636751 101 nordicUUID.type = BLE_UUID_TYPE_BLE;
yihui 1:fc2f9d636751 102 } else {
yihui 1:fc2f9d636751 103 if (!lookupConvertedUUIDTable(uuid.getBaseUUID(), &nordicUUID.type)) {
yihui 1:fc2f9d636751 104 nordicUUID.type = custom_add_uuid_base(uuid.getBaseUUID());
yihui 1:fc2f9d636751 105 addToConvertedUUIDTable(uuid.getBaseUUID(), nordicUUID.type);
yihui 1:fc2f9d636751 106 }
yihui 1:fc2f9d636751 107 }
yihui 1:fc2f9d636751 108
yihui 1:fc2f9d636751 109 return nordicUUID;
yihui 1:fc2f9d636751 110 }
yihui 1:fc2f9d636751 111
yihui 1:fc2f9d636751 112 /**************************************************************************/
yihui 1:fc2f9d636751 113 /*!
yihui 1:fc2f9d636751 114 @brief Adds the base UUID to the custom service. All UUIDs used
yihui 1:fc2f9d636751 115 by this service are based on this 128-bit UUID.
yihui 1:fc2f9d636751 116
yihui 1:fc2f9d636751 117 @note This UUID needs to be added to the SoftDevice stack before
yihui 1:fc2f9d636751 118 adding the service's primary service via
yihui 1:fc2f9d636751 119 'sd_ble_gatts_service_add'
yihui 1:fc2f9d636751 120
yihui 1:fc2f9d636751 121 @param[in] p_uuid_base A pointer to the 128-bit UUID array (8*16)
yihui 1:fc2f9d636751 122
yihui 1:fc2f9d636751 123 @returns The UUID type.
yihui 1:fc2f9d636751 124 A return value of 0 should be considered an error.
yihui 1:fc2f9d636751 125
yihui 1:fc2f9d636751 126 @retval 0x00 BLE_UUID_TYPE_UNKNOWN
yihui 1:fc2f9d636751 127 @retval 0x01 BLE_UUID_TYPE_BLE
yihui 1:fc2f9d636751 128 @retval 0x02 BLE_UUID_TYPE_VENDOR_BEGIN
yihui 1:fc2f9d636751 129
yihui 1:fc2f9d636751 130 @section EXAMPLE
yihui 1:fc2f9d636751 131 @code
yihui 1:fc2f9d636751 132
yihui 1:fc2f9d636751 133 // Take note that bytes 2/3 are blank since these are used to identify
yihui 1:fc2f9d636751 134 // the primary service and individual characteristics
yihui 1:fc2f9d636751 135 #define CFG_CUSTOM_UUID_BASE "\x6E\x40\x00\x00\xB5\xA3\xF3\x93\xE0\xA9\xE5\x0E\x24\xDC\xCA\x9E"
yihui 1:fc2f9d636751 136
yihui 1:fc2f9d636751 137 uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE);
yihui 1:fc2f9d636751 138 ASSERT(uuid_type > 0, ERROR_NOT_FOUND);
yihui 1:fc2f9d636751 139
yihui 1:fc2f9d636751 140 // We can now safely add the primary service and any characteristics
yihui 1:fc2f9d636751 141 // for our custom service ...
yihui 1:fc2f9d636751 142
yihui 1:fc2f9d636751 143 @endcode
yihui 1:fc2f9d636751 144 */
yihui 1:fc2f9d636751 145 /**************************************************************************/
yihui 1:fc2f9d636751 146 uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
yihui 1:fc2f9d636751 147 {
yihui 1:fc2f9d636751 148 ble_uuid128_t base_uuid;
yihui 1:fc2f9d636751 149 uint8_t uuid_type = 0;
yihui 1:fc2f9d636751 150
yihui 1:fc2f9d636751 151 /* Reverse the bytes since ble_uuid128_t is LSB */
yihui 1:fc2f9d636751 152 for (unsigned i = 0; i < LENGTH_OF_LONG_UUID; i++) {
yihui 1:fc2f9d636751 153 base_uuid.uuid128[i] = p_uuid_base[LENGTH_OF_LONG_UUID - 1 - i];
yihui 1:fc2f9d636751 154 }
yihui 1:fc2f9d636751 155
yihui 1:fc2f9d636751 156 ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0);
yihui 1:fc2f9d636751 157
yihui 1:fc2f9d636751 158 return uuid_type;
yihui 1:fc2f9d636751 159 }
yihui 1:fc2f9d636751 160
yihui 1:fc2f9d636751 161 /**************************************************************************/
yihui 1:fc2f9d636751 162 /*!
yihui 1:fc2f9d636751 163
yihui 1:fc2f9d636751 164 */
yihui 1:fc2f9d636751 165 /**************************************************************************/
yihui 1:fc2f9d636751 166 error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
yihui 1:fc2f9d636751 167 ble_uuid_t *p_uuid)
yihui 1:fc2f9d636751 168 {
yihui 1:fc2f9d636751 169 LongUUIDBytes_t uuid_base_le;
yihui 1:fc2f9d636751 170
yihui 1:fc2f9d636751 171 /* Reverse the bytes since ble_uuid128_t is LSB */
yihui 1:fc2f9d636751 172 for (uint8_t i = 0; i < LENGTH_OF_LONG_UUID; i++) {
yihui 1:fc2f9d636751 173 uuid_base_le[i] = p_uuid_base[LENGTH_OF_LONG_UUID - 1 - i];
yihui 1:fc2f9d636751 174 }
yihui 1:fc2f9d636751 175
yihui 1:fc2f9d636751 176 ASSERT_STATUS( sd_ble_uuid_decode(LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid));
yihui 1:fc2f9d636751 177
yihui 1:fc2f9d636751 178 return ERROR_NONE;
yihui 1:fc2f9d636751 179 }
yihui 1:fc2f9d636751 180
yihui 1:fc2f9d636751 181 /**************************************************************************/
yihui 1:fc2f9d636751 182 /*!
yihui 1:fc2f9d636751 183 @brief Adds a new characteristic to the custom service, assigning
yihui 1:fc2f9d636751 184 properties, a UUID add-on value, etc.
yihui 1:fc2f9d636751 185
yihui 1:fc2f9d636751 186 @param[in] service_handle
yihui 1:fc2f9d636751 187 @param[in] p_uuid The 16-bit value to add to the base UUID
yihui 1:fc2f9d636751 188 for this characteristic (normally >1
yihui 1:fc2f9d636751 189 since 1 is typically used by the primary
yihui 1:fc2f9d636751 190 service).
yihui 1:fc2f9d636751 191 @param[in] char_props The characteristic properties, as
yihui 1:fc2f9d636751 192 defined by ble_gatt_char_props_t
yihui 1:fc2f9d636751 193 @param[in] max_length The maximum length of this characeristic
yihui 1:fc2f9d636751 194 @param[in] p_char_handle
yihui 1:fc2f9d636751 195
yihui 1:fc2f9d636751 196 @returns
yihui 1:fc2f9d636751 197 @retval ERROR_NONE Everything executed normally
yihui 1:fc2f9d636751 198 */
yihui 1:fc2f9d636751 199 /**************************************************************************/
yihui 1:fc2f9d636751 200 error_t custom_add_in_characteristic(uint16_t service_handle,
yihui 1:fc2f9d636751 201 ble_uuid_t *p_uuid,
yihui 1:fc2f9d636751 202 uint8_t properties,
yihui 1:fc2f9d636751 203 uint8_t *p_data,
yihui 1:fc2f9d636751 204 uint16_t min_length,
yihui 1:fc2f9d636751 205 uint16_t max_length,
yihui 1:fc2f9d636751 206 bool readAuthorization,
yihui 1:fc2f9d636751 207 bool writeAuthorization,
yihui 1:fc2f9d636751 208 ble_gatts_char_handles_t *p_char_handle)
yihui 1:fc2f9d636751 209 {
yihui 1:fc2f9d636751 210 /* Characteristic metadata */
yihui 1:fc2f9d636751 211 ble_gatts_attr_md_t cccd_md;
yihui 1:fc2f9d636751 212 ble_gatt_char_props_t char_props;
yihui 1:fc2f9d636751 213
yihui 1:fc2f9d636751 214 memcpy(&char_props, &properties, 1);
yihui 1:fc2f9d636751 215
yihui 1:fc2f9d636751 216 if (char_props.notify || char_props.indicate) {
yihui 1:fc2f9d636751 217 /* Notification requires cccd */
yihui 1:fc2f9d636751 218 memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t));
yihui 1:fc2f9d636751 219 cccd_md.vloc = BLE_GATTS_VLOC_STACK;
yihui 1:fc2f9d636751 220 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
yihui 1:fc2f9d636751 221 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
yihui 1:fc2f9d636751 222 }
yihui 1:fc2f9d636751 223
yihui 1:fc2f9d636751 224 ble_gatts_char_md_t char_md = {0};
yihui 1:fc2f9d636751 225
yihui 1:fc2f9d636751 226 char_md.char_props = char_props;
yihui 1:fc2f9d636751 227 char_md.p_cccd_md =
yihui 1:fc2f9d636751 228 (char_props.notify || char_props.indicate) ? &cccd_md : NULL;
yihui 1:fc2f9d636751 229
yihui 1:fc2f9d636751 230 /* Attribute declaration */
yihui 1:fc2f9d636751 231 ble_gatts_attr_md_t attr_md = {0};
yihui 1:fc2f9d636751 232
yihui 1:fc2f9d636751 233 attr_md.rd_auth = readAuthorization;
yihui 1:fc2f9d636751 234 attr_md.wr_auth = writeAuthorization;
yihui 1:fc2f9d636751 235
yihui 1:fc2f9d636751 236 attr_md.vloc = BLE_GATTS_VLOC_STACK;
yihui 1:fc2f9d636751 237 attr_md.vlen = (min_length == max_length) ? 0 : 1;
yihui 1:fc2f9d636751 238
yihui 1:fc2f9d636751 239 if (char_props.read || char_props.notify || char_props.indicate) {
yihui 1:fc2f9d636751 240 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
yihui 1:fc2f9d636751 241 }
yihui 1:fc2f9d636751 242
yihui 1:fc2f9d636751 243 if (char_props.write || char_props.write_wo_resp) {
yihui 1:fc2f9d636751 244 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
yihui 1:fc2f9d636751 245 }
yihui 1:fc2f9d636751 246
yihui 1:fc2f9d636751 247 ble_gatts_attr_t attr_char_value = {0};
yihui 1:fc2f9d636751 248
yihui 1:fc2f9d636751 249 attr_char_value.p_uuid = p_uuid;
yihui 1:fc2f9d636751 250 attr_char_value.p_attr_md = &attr_md;
yihui 1:fc2f9d636751 251 attr_char_value.init_len = min_length;
yihui 1:fc2f9d636751 252 attr_char_value.max_len = max_length;
yihui 1:fc2f9d636751 253 attr_char_value.p_value = p_data;
yihui 1:fc2f9d636751 254
yihui 1:fc2f9d636751 255 ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle,
yihui 1:fc2f9d636751 256 &char_md,
yihui 1:fc2f9d636751 257 &attr_char_value,
yihui 1:fc2f9d636751 258 p_char_handle));
yihui 1:fc2f9d636751 259
yihui 1:fc2f9d636751 260 return ERROR_NONE;
yihui 1:fc2f9d636751 261 }
yihui 1:fc2f9d636751 262
yihui 1:fc2f9d636751 263
yihui 1:fc2f9d636751 264
yihui 1:fc2f9d636751 265 /**************************************************************************/
yihui 1:fc2f9d636751 266 /*!
yihui 1:fc2f9d636751 267 @brief Adds a new descriptor to the custom service, assigning
yihui 1:fc2f9d636751 268 value, a UUID add-on value, etc.
yihui 1:fc2f9d636751 269
yihui 1:fc2f9d636751 270 @param[in] char_handle
yihui 1:fc2f9d636751 271 @param[in] p_uuid The 16-bit value to add to the base UUID
yihui 1:fc2f9d636751 272 for this descriptor (normally >1
yihui 1:fc2f9d636751 273 since 1 is typically used by the primary
yihui 1:fc2f9d636751 274 service).
yihui 1:fc2f9d636751 275 @param[in] max_length The maximum length of this descriptor
yihui 1:fc2f9d636751 276
yihui 1:fc2f9d636751 277 @returns
yihui 1:fc2f9d636751 278 @retval ERROR_NONE Everything executed normally
yihui 1:fc2f9d636751 279 */
yihui 1:fc2f9d636751 280 /**************************************************************************/
yihui 1:fc2f9d636751 281 error_t custom_add_in_descriptor(uint16_t char_handle,
yihui 1:fc2f9d636751 282 ble_uuid_t *p_uuid,
yihui 1:fc2f9d636751 283 uint8_t *p_data,
yihui 1:fc2f9d636751 284 uint16_t min_length,
yihui 1:fc2f9d636751 285 uint16_t max_length,
yihui 1:fc2f9d636751 286 uint16_t *p_desc_handle)
yihui 1:fc2f9d636751 287 {
yihui 1:fc2f9d636751 288 /* Descriptor metadata */
yihui 1:fc2f9d636751 289 ble_gatts_attr_md_t desc_md = {0};
yihui 1:fc2f9d636751 290
yihui 1:fc2f9d636751 291 desc_md.vloc = BLE_GATTS_VLOC_STACK;
yihui 1:fc2f9d636751 292 desc_md.vlen = (min_length == max_length) ? 0 : 1;
yihui 1:fc2f9d636751 293
yihui 1:fc2f9d636751 294 /* Make it readable and writable */
yihui 1:fc2f9d636751 295 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm);
yihui 1:fc2f9d636751 296 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm);
yihui 1:fc2f9d636751 297
yihui 1:fc2f9d636751 298 ble_gatts_attr_t attr_desc = {0};
yihui 1:fc2f9d636751 299
yihui 1:fc2f9d636751 300 attr_desc.p_uuid = p_uuid;
yihui 1:fc2f9d636751 301 attr_desc.p_attr_md = &desc_md;
yihui 1:fc2f9d636751 302 attr_desc.init_len = min_length;
yihui 1:fc2f9d636751 303 attr_desc.max_len = max_length;
yihui 1:fc2f9d636751 304 attr_desc.p_value = p_data;
yihui 1:fc2f9d636751 305
yihui 1:fc2f9d636751 306 ASSERT_STATUS ( sd_ble_gatts_descriptor_add(char_handle,
yihui 1:fc2f9d636751 307 &attr_desc,
yihui 1:fc2f9d636751 308 p_desc_handle));
yihui 1:fc2f9d636751 309
yihui 1:fc2f9d636751 310 return ERROR_NONE;
yihui 1:fc2f9d636751 311 }