added debugging

Fork of BLE_nRF8001 by RedBearLab

Committer:
jn80842
Date:
Mon Nov 10 01:24:23 2014 +0000
Revision:
2:7805a5595aab
Parent:
0:075ea2812998
just added debugging

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RedBearLab 0:075ea2812998 1
RedBearLab 0:075ea2812998 2 #include "BLEAttribute.h"
RedBearLab 0:075ea2812998 3 #include "BLEService.h"
RedBearLab 0:075ea2812998 4 #include "BLECharacteristic.h"
RedBearLab 0:075ea2812998 5 #include "BLEDescriptor.h"
RedBearLab 0:075ea2812998 6 #include "BLEUuid.h"
RedBearLab 0:075ea2812998 7
RedBearLab 0:075ea2812998 8 #include "nRF8001.h"
RedBearLab 0:075ea2812998 9
RedBearLab 0:075ea2812998 10 //#define NRF_8001_DEBUG
RedBearLab 0:075ea2812998 11
RedBearLab 0:075ea2812998 12 #define ADVERTISING_INTERVAL 0x050
RedBearLab 0:075ea2812998 13
RedBearLab 0:075ea2812998 14 struct setupMsgData {
RedBearLab 0:075ea2812998 15 unsigned char length;
RedBearLab 0:075ea2812998 16 unsigned char cmd;
RedBearLab 0:075ea2812998 17 unsigned char type;
RedBearLab 0:075ea2812998 18 unsigned char offset;
RedBearLab 0:075ea2812998 19 unsigned char data[28];
RedBearLab 0:075ea2812998 20 };
RedBearLab 0:075ea2812998 21
RedBearLab 0:075ea2812998 22 #define NB_BASE_SETUP_MESSAGES 7
RedBearLab 0:075ea2812998 23
RedBearLab 0:075ea2812998 24 /* Store the setup for the nRF8001 in the flash of the AVR to save on RAM */
RedBearLab 0:075ea2812998 25 static hal_aci_data_t baseSetupMsgs[NB_BASE_SETUP_MESSAGES] PROGMEM = {\
RedBearLab 0:075ea2812998 26 {0x00,\
RedBearLab 0:075ea2812998 27 {\
RedBearLab 0:075ea2812998 28 0x07,0x06,0x00,0x00,0x03,0x02,0x41,0xfe,\
RedBearLab 0:075ea2812998 29 },\
RedBearLab 0:075ea2812998 30 },\
RedBearLab 0:075ea2812998 31 {0x00,\
RedBearLab 0:075ea2812998 32 {\
RedBearLab 0:075ea2812998 33 0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x06,0x00,0x06,\
RedBearLab 0:075ea2812998 34 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 35 },\
RedBearLab 0:075ea2812998 36 },\
RedBearLab 0:075ea2812998 37 {0x00,\
RedBearLab 0:075ea2812998 38 {\
RedBearLab 0:075ea2812998 39 0x1f,0x06,0x10,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 40 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x90,0x00,0xff,\
RedBearLab 0:075ea2812998 41 },\
RedBearLab 0:075ea2812998 42 },\
RedBearLab 0:075ea2812998 43 {0x00,\
RedBearLab 0:075ea2812998 44 {\
RedBearLab 0:075ea2812998 45 0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 46 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,\
RedBearLab 0:075ea2812998 47 },\
RedBearLab 0:075ea2812998 48 },\
RedBearLab 0:075ea2812998 49 {0x00,\
RedBearLab 0:075ea2812998 50 {\
RedBearLab 0:075ea2812998 51 0x05,0x06,0x10,0x54,0x00,0x02,\
RedBearLab 0:075ea2812998 52 },\
RedBearLab 0:075ea2812998 53 },\
RedBearLab 0:075ea2812998 54 {0x00,\
RedBearLab 0:075ea2812998 55 {\
RedBearLab 0:075ea2812998 56 0x19,0x06,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 57 0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 58 },\
RedBearLab 0:075ea2812998 59 },\
RedBearLab 0:075ea2812998 60 {0x00,\
RedBearLab 0:075ea2812998 61 {\
RedBearLab 0:075ea2812998 62 0x19,0x06,0x70,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 63 0x00,0x00,0x00,0x00,0x00,0x00,\
RedBearLab 0:075ea2812998 64 },\
RedBearLab 0:075ea2812998 65 },\
RedBearLab 0:075ea2812998 66 };
RedBearLab 0:075ea2812998 67
RedBearLab 0:075ea2812998 68 void __ble_assert(const char *file, uint16_t line)
RedBearLab 0:075ea2812998 69 {
RedBearLab 0:075ea2812998 70 serial.printf("ERROR ");
RedBearLab 0:075ea2812998 71 serial.printf(file);
RedBearLab 0:075ea2812998 72 serial.printf(": ");
RedBearLab 0:075ea2812998 73 serial.printf("%d\n",line);
RedBearLab 0:075ea2812998 74 while(1);
RedBearLab 0:075ea2812998 75 }
RedBearLab 0:075ea2812998 76
RedBearLab 0:075ea2812998 77 /** crc function to re-calulate the CRC after making changes to the setup data.
RedBearLab 0:075ea2812998 78 */
RedBearLab 0:075ea2812998 79 uint16_t crc_16_ccitt(uint16_t crc, uint8_t * data_in, uint16_t data_len) {
RedBearLab 0:075ea2812998 80
RedBearLab 0:075ea2812998 81 uint16_t i;
RedBearLab 0:075ea2812998 82
RedBearLab 0:075ea2812998 83 for(i = 0; i < data_len; i++)
RedBearLab 0:075ea2812998 84 {
RedBearLab 0:075ea2812998 85 crc = (unsigned char)(crc >> 8) | (crc << 8);
RedBearLab 0:075ea2812998 86 crc ^= data_in[i];
RedBearLab 0:075ea2812998 87 crc ^= (unsigned char)(crc & 0xff) >> 4;
RedBearLab 0:075ea2812998 88 crc ^= (crc << 8) << 4;
RedBearLab 0:075ea2812998 89 crc ^= ((crc & 0xff) << 4) << 1;
RedBearLab 0:075ea2812998 90 }
RedBearLab 0:075ea2812998 91
RedBearLab 0:075ea2812998 92 return crc;
RedBearLab 0:075ea2812998 93 }
RedBearLab 0:075ea2812998 94
RedBearLab 0:075ea2812998 95 nRF8001::nRF8001(DigitalInOut *req, DigitalInOut *rdy, DigitalInOut *rst) :
RedBearLab 0:075ea2812998 96 _pipeInfo(NULL),
RedBearLab 0:075ea2812998 97 _numPipeInfo(0),
RedBearLab 0:075ea2812998 98
RedBearLab 0:075ea2812998 99 _crcSeed(0xFFFF),
RedBearLab 0:075ea2812998 100
RedBearLab 0:075ea2812998 101 _eventListener(NULL)
RedBearLab 0:075ea2812998 102 {
RedBearLab 0:075ea2812998 103 this->_aciState.aci_pins.reqn_pin = req;
RedBearLab 0:075ea2812998 104 this->_aciState.aci_pins.rdyn_pin = rdy;
RedBearLab 0:075ea2812998 105
RedBearLab 0:075ea2812998 106 if (rst == NULL) {
RedBearLab 0:075ea2812998 107 this->_aciState.aci_pins.board_name = REDBEARLAB_SHIELD_V1_1;
RedBearLab 0:075ea2812998 108 }
RedBearLab 0:075ea2812998 109 else {
RedBearLab 0:075ea2812998 110 this->_aciState.aci_pins.board_name = BOARD_DEFAULT;
RedBearLab 0:075ea2812998 111 }
RedBearLab 0:075ea2812998 112
RedBearLab 0:075ea2812998 113 this->_aciState.aci_pins.reset_pin = rst;
RedBearLab 0:075ea2812998 114 this->_aciState.aci_pins.active_pin = NULL;
RedBearLab 0:075ea2812998 115
RedBearLab 0:075ea2812998 116 this->_aciState.aci_pins.interface_is_interrupt = false;
RedBearLab 0:075ea2812998 117 this->_aciState.aci_pins.interrupt_number = 1;
RedBearLab 0:075ea2812998 118 }
RedBearLab 0:075ea2812998 119
RedBearLab 0:075ea2812998 120 nRF8001::~nRF8001() {
RedBearLab 0:075ea2812998 121 if (this->_pipeInfo) {
RedBearLab 0:075ea2812998 122 free(this->_pipeInfo);
RedBearLab 0:075ea2812998 123 }
RedBearLab 0:075ea2812998 124 }
RedBearLab 0:075ea2812998 125
RedBearLab 0:075ea2812998 126
RedBearLab 0:075ea2812998 127
RedBearLab 0:075ea2812998 128 void nRF8001::setEventListener(nRF8001EventListener* eventListener) {
RedBearLab 0:075ea2812998 129 this->_eventListener = eventListener;
RedBearLab 0:075ea2812998 130 }
RedBearLab 0:075ea2812998 131
RedBearLab 0:075ea2812998 132 void nRF8001::begin(const unsigned char* advertisementData,
RedBearLab 0:075ea2812998 133 unsigned char advertisementDataLength,
RedBearLab 0:075ea2812998 134 const unsigned char* scanData,
RedBearLab 0:075ea2812998 135 unsigned char scanDataLength,
RedBearLab 0:075ea2812998 136 BLEAttribute** attributes,
RedBearLab 0:075ea2812998 137 unsigned char numAttributes)
RedBearLab 0:075ea2812998 138 {
RedBearLab 0:075ea2812998 139 unsigned char numPipedCharacteristics = 0;
RedBearLab 0:075ea2812998 140
RedBearLab 0:075ea2812998 141 for (int i = 0; i < numAttributes; i++) {
RedBearLab 0:075ea2812998 142 BLEAttribute* attribute = attributes[i];
RedBearLab 0:075ea2812998 143
RedBearLab 0:075ea2812998 144 if (attribute->type() == BLETypeCharacteristic) {
RedBearLab 0:075ea2812998 145 BLECharacteristic* characteristic = (BLECharacteristic *)attribute;
RedBearLab 0:075ea2812998 146
RedBearLab 0:075ea2812998 147 if (characteristic->properties()) {
RedBearLab 0:075ea2812998 148 numPipedCharacteristics++;
RedBearLab 0:075ea2812998 149 }
RedBearLab 0:075ea2812998 150 }
RedBearLab 0:075ea2812998 151 }
RedBearLab 0:075ea2812998 152
RedBearLab 0:075ea2812998 153 this->_pipeInfo = (struct pipeInfo*)malloc(sizeof(struct pipeInfo) * numPipedCharacteristics);
RedBearLab 0:075ea2812998 154
RedBearLab 0:075ea2812998 155 lib_aci_init(&this->_aciState, false);
RedBearLab 0:075ea2812998 156
RedBearLab 0:075ea2812998 157 this->waitForSetupMode();
RedBearLab 0:075ea2812998 158
RedBearLab 0:075ea2812998 159 hal_aci_data_t setupMsg;
RedBearLab 0:075ea2812998 160 struct setupMsgData* setupMsgData = (struct setupMsgData*)setupMsg.buffer;
RedBearLab 0:075ea2812998 161
RedBearLab 0:075ea2812998 162 setupMsg.status_byte = 0;
RedBearLab 0:075ea2812998 163
RedBearLab 0:075ea2812998 164 for (int i = 0; i < NB_BASE_SETUP_MESSAGES; i++) {
RedBearLab 0:075ea2812998 165 int setupMsgSize = pgm_read_byte_near(&baseSetupMsgs[i].buffer[0]) + 2;
RedBearLab 0:075ea2812998 166
RedBearLab 0:075ea2812998 167 memcpy_P(&setupMsg, &baseSetupMsgs[i], setupMsgSize);
RedBearLab 0:075ea2812998 168
RedBearLab 0:075ea2812998 169 if (i == 1) {
RedBearLab 0:075ea2812998 170 setupMsgData->data[6] = numPipedCharacteristics;
RedBearLab 0:075ea2812998 171 setupMsgData->data[8] = numPipedCharacteristics;
RedBearLab 0:075ea2812998 172 } else if (i == 2 && advertisementData && advertisementDataLength) {
RedBearLab 0:075ea2812998 173 setupMsgData->data[22] = 0x40;
RedBearLab 0:075ea2812998 174 } else if (i == 3 && scanData && scanDataLength) {
RedBearLab 0:075ea2812998 175 setupMsgData->data[12] = 0x40;
RedBearLab 0:075ea2812998 176 } else if (i == 5 && advertisementData && advertisementDataLength) {
RedBearLab 0:075ea2812998 177 memcpy(setupMsgData->data, advertisementData, advertisementDataLength);
RedBearLab 0:075ea2812998 178 } else if (i == 6 && scanData && scanDataLength) {
RedBearLab 0:075ea2812998 179 memcpy(setupMsgData->data, scanData, scanDataLength);
RedBearLab 0:075ea2812998 180 }
RedBearLab 0:075ea2812998 181
RedBearLab 0:075ea2812998 182 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 183 }
RedBearLab 0:075ea2812998 184
RedBearLab 0:075ea2812998 185 // GATT
RedBearLab 0:075ea2812998 186 unsigned char gattSetupMsgOffset = 0;
RedBearLab 0:075ea2812998 187 unsigned short handle = 1;
RedBearLab 0:075ea2812998 188 unsigned char pipe = 1;
RedBearLab 0:075ea2812998 189 unsigned char numPiped = 0;
RedBearLab 0:075ea2812998 190
RedBearLab 0:075ea2812998 191 for (int i = 0; i < numAttributes; i++) {
RedBearLab 0:075ea2812998 192 BLEAttribute* attribute = attributes[i];
RedBearLab 0:075ea2812998 193 BLEUuid uuid = BLEUuid(attribute->uuid());
RedBearLab 0:075ea2812998 194
RedBearLab 0:075ea2812998 195 if (attribute->type() == BLETypeService) {
RedBearLab 0:075ea2812998 196 BLEService* service = (BLEService *)attribute;
RedBearLab 0:075ea2812998 197
RedBearLab 0:075ea2812998 198 setupMsgData->length = 12 + uuid.length();
RedBearLab 0:075ea2812998 199 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 200 setupMsgData->type = 0x20;
RedBearLab 0:075ea2812998 201 setupMsgData->offset = gattSetupMsgOffset;
RedBearLab 0:075ea2812998 202
RedBearLab 0:075ea2812998 203 setupMsgData->data[0] = 0x04;
RedBearLab 0:075ea2812998 204 setupMsgData->data[1] = 0x04;
RedBearLab 0:075ea2812998 205 setupMsgData->data[2] = uuid.length();
RedBearLab 0:075ea2812998 206 setupMsgData->data[3] = uuid.length();
RedBearLab 0:075ea2812998 207
RedBearLab 0:075ea2812998 208 setupMsgData->data[4] = (handle >> 8) & 0xff;
RedBearLab 0:075ea2812998 209 setupMsgData->data[5] = handle & 0xff;
RedBearLab 0:075ea2812998 210 handle++;
RedBearLab 0:075ea2812998 211
RedBearLab 0:075ea2812998 212 setupMsgData->data[6] = (service->type() >> 8) & 0xff;
RedBearLab 0:075ea2812998 213 setupMsgData->data[7] = service->type() & 0xff;
RedBearLab 0:075ea2812998 214
RedBearLab 0:075ea2812998 215 setupMsgData->data[8] = ACI_STORE_LOCAL;
RedBearLab 0:075ea2812998 216
RedBearLab 0:075ea2812998 217 memcpy(&setupMsgData->data[9], uuid.data(), uuid.length());
RedBearLab 0:075ea2812998 218
RedBearLab 0:075ea2812998 219 gattSetupMsgOffset += 9 + uuid.length();
RedBearLab 0:075ea2812998 220
RedBearLab 0:075ea2812998 221 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 222 } else if (attribute->type() == BLETypeCharacteristic) {
RedBearLab 0:075ea2812998 223 BLECharacteristic* characteristic = (BLECharacteristic *)attribute;
RedBearLab 0:075ea2812998 224
RedBearLab 0:075ea2812998 225 struct pipeInfo* pipeInfo = &this->_pipeInfo[numPiped];
RedBearLab 0:075ea2812998 226
RedBearLab 0:075ea2812998 227 memset(pipeInfo, 0, sizeof(struct pipeInfo));
RedBearLab 0:075ea2812998 228
RedBearLab 0:075ea2812998 229 pipeInfo->characteristic = characteristic;
RedBearLab 0:075ea2812998 230
RedBearLab 0:075ea2812998 231 if (characteristic->properties()) {
RedBearLab 0:075ea2812998 232 numPiped++;
RedBearLab 0:075ea2812998 233
RedBearLab 0:075ea2812998 234 pipeInfo->startPipe = pipe;
RedBearLab 0:075ea2812998 235
RedBearLab 0:075ea2812998 236 if (characteristic->properties() & BLENotify) {
RedBearLab 0:075ea2812998 237 pipeInfo->txPipe = pipe;
RedBearLab 0:075ea2812998 238
RedBearLab 0:075ea2812998 239 pipe++;
RedBearLab 0:075ea2812998 240 }
RedBearLab 0:075ea2812998 241
RedBearLab 0:075ea2812998 242 if (characteristic->properties() & BLEIndicate) {
RedBearLab 0:075ea2812998 243 pipeInfo->txAckPipe = pipe;
RedBearLab 0:075ea2812998 244
RedBearLab 0:075ea2812998 245 pipe++;
RedBearLab 0:075ea2812998 246 }
RedBearLab 0:075ea2812998 247
RedBearLab 0:075ea2812998 248 if (characteristic->properties() & BLEWriteWithoutResponse) {
RedBearLab 0:075ea2812998 249 pipeInfo->rxPipe = pipe;
RedBearLab 0:075ea2812998 250
RedBearLab 0:075ea2812998 251 pipe++;
RedBearLab 0:075ea2812998 252 }
RedBearLab 0:075ea2812998 253
RedBearLab 0:075ea2812998 254 if (characteristic->properties() & BLEWrite) {
RedBearLab 0:075ea2812998 255 pipeInfo->rxAckPipe = pipe;
RedBearLab 0:075ea2812998 256
RedBearLab 0:075ea2812998 257 pipe++;
RedBearLab 0:075ea2812998 258 }
RedBearLab 0:075ea2812998 259
RedBearLab 0:075ea2812998 260 if (characteristic->properties() & BLERead) {
RedBearLab 0:075ea2812998 261 pipeInfo->setPipe = pipe;
RedBearLab 0:075ea2812998 262
RedBearLab 0:075ea2812998 263 pipe++;
RedBearLab 0:075ea2812998 264 }
RedBearLab 0:075ea2812998 265 }
RedBearLab 0:075ea2812998 266
RedBearLab 0:075ea2812998 267 setupMsgData->length = 15 + uuid.length();
RedBearLab 0:075ea2812998 268 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 269 setupMsgData->type = 0x20;
RedBearLab 0:075ea2812998 270 setupMsgData->offset = gattSetupMsgOffset;
RedBearLab 0:075ea2812998 271
RedBearLab 0:075ea2812998 272 setupMsgData->data[0] = 0x04;
RedBearLab 0:075ea2812998 273 setupMsgData->data[1] = 0x04;
RedBearLab 0:075ea2812998 274 setupMsgData->data[2] = 3 + uuid.length();
RedBearLab 0:075ea2812998 275 setupMsgData->data[3] = 3 + uuid.length();
RedBearLab 0:075ea2812998 276
RedBearLab 0:075ea2812998 277 setupMsgData->data[4] = (handle >> 8) & 0xff;
RedBearLab 0:075ea2812998 278 setupMsgData->data[5] = handle & 0xff;
RedBearLab 0:075ea2812998 279 handle++;
RedBearLab 0:075ea2812998 280
RedBearLab 0:075ea2812998 281 setupMsgData->data[6] = (characteristic->type() >> 8) & 0xff;
RedBearLab 0:075ea2812998 282 setupMsgData->data[7] = characteristic->type() & 0xff;
RedBearLab 0:075ea2812998 283
RedBearLab 0:075ea2812998 284 setupMsgData->data[8] = ACI_STORE_LOCAL;
RedBearLab 0:075ea2812998 285 setupMsgData->data[9] = characteristic->properties();
RedBearLab 0:075ea2812998 286
RedBearLab 0:075ea2812998 287 setupMsgData->data[10] = handle & 0xff;
RedBearLab 0:075ea2812998 288 setupMsgData->data[11] = (handle >> 8) & 0xff;
RedBearLab 0:075ea2812998 289 pipeInfo->valueHandle = handle;
RedBearLab 0:075ea2812998 290 handle++;
RedBearLab 0:075ea2812998 291
RedBearLab 0:075ea2812998 292 memcpy(&setupMsgData->data[12], uuid.data(), uuid.length());
RedBearLab 0:075ea2812998 293
RedBearLab 0:075ea2812998 294 gattSetupMsgOffset += 12 + uuid.length();
RedBearLab 0:075ea2812998 295
RedBearLab 0:075ea2812998 296 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 297
RedBearLab 0:075ea2812998 298 setupMsgData->length = 12 + characteristic->valueSize();
RedBearLab 0:075ea2812998 299 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 300 setupMsgData->type = 0x20;
RedBearLab 0:075ea2812998 301 setupMsgData->offset = gattSetupMsgOffset;
RedBearLab 0:075ea2812998 302
RedBearLab 0:075ea2812998 303 setupMsgData->data[0] = 0x04;
RedBearLab 0:075ea2812998 304 setupMsgData->data[1] = 0x00;
RedBearLab 0:075ea2812998 305
RedBearLab 0:075ea2812998 306 if (characteristic->fixedLength()) {
RedBearLab 0:075ea2812998 307 setupMsgData->data[0] |= 0x02;
RedBearLab 0:075ea2812998 308 }
RedBearLab 0:075ea2812998 309
RedBearLab 0:075ea2812998 310 if (characteristic->properties() & BLERead) {
RedBearLab 0:075ea2812998 311 setupMsgData->data[1] |= 0x04;
RedBearLab 0:075ea2812998 312 }
RedBearLab 0:075ea2812998 313
RedBearLab 0:075ea2812998 314 if (characteristic->properties() & (BLEWrite | BLEWriteWithoutResponse)) {
RedBearLab 0:075ea2812998 315 setupMsgData->data[0] |= 0x40;
RedBearLab 0:075ea2812998 316 setupMsgData->data[1] |= 0x10;
RedBearLab 0:075ea2812998 317 }
RedBearLab 0:075ea2812998 318
RedBearLab 0:075ea2812998 319 if (characteristic->properties() & BLENotify) {
RedBearLab 0:075ea2812998 320 setupMsgData->data[0] |= 0x10;
RedBearLab 0:075ea2812998 321 }
RedBearLab 0:075ea2812998 322
RedBearLab 0:075ea2812998 323 if (characteristic->properties() & BLEIndicate) {
RedBearLab 0:075ea2812998 324 setupMsgData->data[0] |= 0x20;
RedBearLab 0:075ea2812998 325 }
RedBearLab 0:075ea2812998 326
RedBearLab 0:075ea2812998 327 setupMsgData->data[2] = characteristic->valueSize();
RedBearLab 0:075ea2812998 328 if (characteristic->fixedLength()) {
RedBearLab 0:075ea2812998 329 setupMsgData->data[2]++;
RedBearLab 0:075ea2812998 330 }
RedBearLab 0:075ea2812998 331
RedBearLab 0:075ea2812998 332 setupMsgData->data[3] = characteristic->valueLength();
RedBearLab 0:075ea2812998 333
RedBearLab 0:075ea2812998 334 setupMsgData->data[4] = (pipeInfo->valueHandle >> 8) & 0xff;
RedBearLab 0:075ea2812998 335 setupMsgData->data[5] = pipeInfo->valueHandle & 0xff;
RedBearLab 0:075ea2812998 336
RedBearLab 0:075ea2812998 337 setupMsgData->data[6] = 0x00;
RedBearLab 0:075ea2812998 338 setupMsgData->data[7] = 0x00;
RedBearLab 0:075ea2812998 339
RedBearLab 0:075ea2812998 340 setupMsgData->data[8] = 0x02;
RedBearLab 0:075ea2812998 341
RedBearLab 0:075ea2812998 342 memset(&setupMsgData->data[9], 0x00, characteristic->valueSize());
RedBearLab 0:075ea2812998 343 memcpy(&setupMsgData->data[9], characteristic->value(), characteristic->valueLength());
RedBearLab 0:075ea2812998 344
RedBearLab 0:075ea2812998 345 gattSetupMsgOffset += 9 + characteristic->valueSize();
RedBearLab 0:075ea2812998 346
RedBearLab 0:075ea2812998 347 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 348
RedBearLab 0:075ea2812998 349 if (characteristic->properties() & (BLENotify | BLEIndicate)) {
RedBearLab 0:075ea2812998 350 setupMsgData->length = 14;
RedBearLab 0:075ea2812998 351 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 352 setupMsgData->type = 0x20;
RedBearLab 0:075ea2812998 353 setupMsgData->offset = gattSetupMsgOffset;
RedBearLab 0:075ea2812998 354
RedBearLab 0:075ea2812998 355 setupMsgData->data[0] = 0x46;
RedBearLab 0:075ea2812998 356 setupMsgData->data[1] = 0x14;
RedBearLab 0:075ea2812998 357
RedBearLab 0:075ea2812998 358 setupMsgData->data[2] = 0x03;
RedBearLab 0:075ea2812998 359 setupMsgData->data[3] = 0x02;
RedBearLab 0:075ea2812998 360
RedBearLab 0:075ea2812998 361 setupMsgData->data[4] = (handle >> 8) & 0xff;
RedBearLab 0:075ea2812998 362 setupMsgData->data[5] = handle & 0xff;
RedBearLab 0:075ea2812998 363 pipeInfo->configHandle = handle;
RedBearLab 0:075ea2812998 364 handle++;
RedBearLab 0:075ea2812998 365
RedBearLab 0:075ea2812998 366 setupMsgData->data[6] = 0x29;
RedBearLab 0:075ea2812998 367 setupMsgData->data[7] = 0x02;
RedBearLab 0:075ea2812998 368
RedBearLab 0:075ea2812998 369 setupMsgData->data[8] = ACI_STORE_LOCAL;
RedBearLab 0:075ea2812998 370
RedBearLab 0:075ea2812998 371 setupMsgData->data[9] = 0x00;
RedBearLab 0:075ea2812998 372 setupMsgData->data[10] = 0x00;
RedBearLab 0:075ea2812998 373
RedBearLab 0:075ea2812998 374 gattSetupMsgOffset += 11;
RedBearLab 0:075ea2812998 375
RedBearLab 0:075ea2812998 376 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 377 }
RedBearLab 0:075ea2812998 378 } else if (attribute->type() == BLETypeDescriptor) {
RedBearLab 0:075ea2812998 379 BLEDescriptor* descriptor = (BLEDescriptor *)attribute;
RedBearLab 0:075ea2812998 380
RedBearLab 0:075ea2812998 381 setupMsgData->length = 12 + descriptor->valueSize();
RedBearLab 0:075ea2812998 382 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 383 setupMsgData->type = 0x20;
RedBearLab 0:075ea2812998 384 setupMsgData->offset = gattSetupMsgOffset;
RedBearLab 0:075ea2812998 385
RedBearLab 0:075ea2812998 386 setupMsgData->data[0] = 0x04;
RedBearLab 0:075ea2812998 387 setupMsgData->data[1] = 0x04;
RedBearLab 0:075ea2812998 388
RedBearLab 0:075ea2812998 389 setupMsgData->data[2] = descriptor->valueSize();
RedBearLab 0:075ea2812998 390 setupMsgData->data[3] = descriptor->valueLength();
RedBearLab 0:075ea2812998 391
RedBearLab 0:075ea2812998 392 setupMsgData->data[4] = (handle >> 8) & 0xff;
RedBearLab 0:075ea2812998 393 setupMsgData->data[5] = handle & 0xff;
RedBearLab 0:075ea2812998 394 handle++;
RedBearLab 0:075ea2812998 395
RedBearLab 0:075ea2812998 396 setupMsgData->data[6] = uuid.data()[1];
RedBearLab 0:075ea2812998 397 setupMsgData->data[7] = uuid.data()[0];
RedBearLab 0:075ea2812998 398
RedBearLab 0:075ea2812998 399 setupMsgData->data[8] = ACI_STORE_LOCAL;
RedBearLab 0:075ea2812998 400
RedBearLab 0:075ea2812998 401 memcpy(&setupMsgData->data[9], descriptor->value(), descriptor->valueLength());
RedBearLab 0:075ea2812998 402
RedBearLab 0:075ea2812998 403 gattSetupMsgOffset += 9 + descriptor->valueSize();
RedBearLab 0:075ea2812998 404
RedBearLab 0:075ea2812998 405 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 406 }
RedBearLab 0:075ea2812998 407 }
RedBearLab 0:075ea2812998 408
RedBearLab 0:075ea2812998 409 this->_numPipeInfo = numPiped;
RedBearLab 0:075ea2812998 410
RedBearLab 0:075ea2812998 411 // terminator
RedBearLab 0:075ea2812998 412 setupMsgData->length = 4;
RedBearLab 0:075ea2812998 413 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 414 setupMsgData->type = 0x20;
RedBearLab 0:075ea2812998 415 setupMsgData->offset = gattSetupMsgOffset;
RedBearLab 0:075ea2812998 416
RedBearLab 0:075ea2812998 417 setupMsgData->data[0] = 0x00;
RedBearLab 0:075ea2812998 418
RedBearLab 0:075ea2812998 419 gattSetupMsgOffset += 6;
RedBearLab 0:075ea2812998 420
RedBearLab 0:075ea2812998 421 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 422
RedBearLab 0:075ea2812998 423 // pipes
RedBearLab 0:075ea2812998 424 unsigned char pipeSetupMsgOffet = 0;
RedBearLab 0:075ea2812998 425
RedBearLab 0:075ea2812998 426 for (int i = 0; i < numPiped; i++) {
RedBearLab 0:075ea2812998 427 struct pipeInfo pipeInfo = this->_pipeInfo[i];
RedBearLab 0:075ea2812998 428
RedBearLab 0:075ea2812998 429 setupMsgData->length = 13;
RedBearLab 0:075ea2812998 430 setupMsgData->cmd = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 431 setupMsgData->type = 0x40;
RedBearLab 0:075ea2812998 432 setupMsgData->offset = pipeSetupMsgOffet;
RedBearLab 0:075ea2812998 433
RedBearLab 0:075ea2812998 434 setupMsgData->data[0] = 0x00;
RedBearLab 0:075ea2812998 435 setupMsgData->data[1] = 0x00;
RedBearLab 0:075ea2812998 436
RedBearLab 0:075ea2812998 437 setupMsgData->data[2] = pipeInfo.startPipe;
RedBearLab 0:075ea2812998 438
RedBearLab 0:075ea2812998 439 setupMsgData->data[3] = 0x00;
RedBearLab 0:075ea2812998 440 setupMsgData->data[4] = 0x00;
RedBearLab 0:075ea2812998 441
RedBearLab 0:075ea2812998 442 setupMsgData->data[5] = 0x04;
RedBearLab 0:075ea2812998 443
RedBearLab 0:075ea2812998 444 setupMsgData->data[6] = (pipeInfo.valueHandle >> 8) & 0xff;
RedBearLab 0:075ea2812998 445 setupMsgData->data[7] = pipeInfo.valueHandle & 0xff;
RedBearLab 0:075ea2812998 446
RedBearLab 0:075ea2812998 447 setupMsgData->data[8] = (pipeInfo.configHandle >> 8) & 0xff;
RedBearLab 0:075ea2812998 448 setupMsgData->data[9] = pipeInfo.configHandle & 0xff;
RedBearLab 0:075ea2812998 449
RedBearLab 0:075ea2812998 450 if (pipeInfo.characteristic->properties() & BLEIndicate) {
RedBearLab 0:075ea2812998 451 setupMsgData->data[4] |= 0x04; // TX Ack
RedBearLab 0:075ea2812998 452 }
RedBearLab 0:075ea2812998 453
RedBearLab 0:075ea2812998 454 if (pipeInfo.characteristic->properties() & BLENotify) {
RedBearLab 0:075ea2812998 455 setupMsgData->data[4] |= 0x02; // TX
RedBearLab 0:075ea2812998 456 }
RedBearLab 0:075ea2812998 457
RedBearLab 0:075ea2812998 458 if (pipeInfo.characteristic->properties() & BLEWriteWithoutResponse) {
RedBearLab 0:075ea2812998 459 setupMsgData->data[4] |= 0x08; // RX Ack
RedBearLab 0:075ea2812998 460 }
RedBearLab 0:075ea2812998 461
RedBearLab 0:075ea2812998 462 if (pipeInfo.characteristic->properties() & BLEWrite) {
RedBearLab 0:075ea2812998 463 setupMsgData->data[4] |= 0x10; // RX Ack
RedBearLab 0:075ea2812998 464 }
RedBearLab 0:075ea2812998 465
RedBearLab 0:075ea2812998 466 if (pipeInfo.characteristic->properties() & BLERead) {
RedBearLab 0:075ea2812998 467 setupMsgData->data[4] |= 0x80; // Set
RedBearLab 0:075ea2812998 468 }
RedBearLab 0:075ea2812998 469
RedBearLab 0:075ea2812998 470 pipeSetupMsgOffet += 10;
RedBearLab 0:075ea2812998 471
RedBearLab 0:075ea2812998 472 this->sendSetupMessage(&setupMsg);
RedBearLab 0:075ea2812998 473 }
RedBearLab 0:075ea2812998 474
RedBearLab 0:075ea2812998 475 this->sendCrc();
RedBearLab 0:075ea2812998 476 }
RedBearLab 0:075ea2812998 477
RedBearLab 0:075ea2812998 478 void nRF8001::poll() {
RedBearLab 0:075ea2812998 479 // We enter the if statement only when there is a ACI event available to be processed
RedBearLab 0:075ea2812998 480 if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
RedBearLab 0:075ea2812998 481 aci_evt_t* aciEvt;
RedBearLab 0:075ea2812998 482 aciEvt = &this->_aciData.evt;
RedBearLab 0:075ea2812998 483
RedBearLab 0:075ea2812998 484 switch(aciEvt->evt_opcode) {
RedBearLab 0:075ea2812998 485 /**
RedBearLab 0:075ea2812998 486 As soon as you reset the nRF8001 you will get an ACI Device Started Event
RedBearLab 0:075ea2812998 487 */
RedBearLab 0:075ea2812998 488 case ACI_EVT_DEVICE_STARTED: {
RedBearLab 0:075ea2812998 489 this->_aciState.data_credit_total = aciEvt->params.device_started.credit_available;
RedBearLab 0:075ea2812998 490 switch(aciEvt->params.device_started.device_mode) {
RedBearLab 0:075ea2812998 491 case ACI_DEVICE_SETUP:
RedBearLab 0:075ea2812998 492 /**
RedBearLab 0:075ea2812998 493 When the device is in the setup mode
RedBearLab 0:075ea2812998 494 */
RedBearLab 0:075ea2812998 495 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 496 Serial.println(F("Evt Device Started: Setup"));
RedBearLab 0:075ea2812998 497 #endif
RedBearLab 0:075ea2812998 498 break;
RedBearLab 0:075ea2812998 499
RedBearLab 0:075ea2812998 500 case ACI_DEVICE_STANDBY:
RedBearLab 0:075ea2812998 501 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 502 Serial.println(F("Evt Device Started: Standby"));
RedBearLab 0:075ea2812998 503 #endif
RedBearLab 0:075ea2812998 504 //Looking for an iPhone by sending radio advertisements
RedBearLab 0:075ea2812998 505 //When an iPhone connects to us we will get an ACI_EVT_CONNECTED event from the nRF8001
RedBearLab 0:075ea2812998 506 if (aciEvt->params.device_started.hw_error) {
RedBearLab 0:075ea2812998 507 delay(20); //Handle the HW error event correctly.
RedBearLab 0:075ea2812998 508 } else {
RedBearLab 0:075ea2812998 509 lib_aci_connect(0/* in seconds : 0 means forever */, ADVERTISING_INTERVAL);
RedBearLab 0:075ea2812998 510 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 511 Serial.println(F("Advertising started"));
RedBearLab 0:075ea2812998 512 #endif
RedBearLab 0:075ea2812998 513 }
RedBearLab 0:075ea2812998 514 break;
RedBearLab 0:075ea2812998 515 }
RedBearLab 0:075ea2812998 516 }
RedBearLab 0:075ea2812998 517 break; //ACI Device Started Event
RedBearLab 0:075ea2812998 518
RedBearLab 0:075ea2812998 519 case ACI_EVT_CMD_RSP:
RedBearLab 0:075ea2812998 520 //If an ACI command response event comes with an error -> stop
RedBearLab 0:075ea2812998 521 if (ACI_STATUS_SUCCESS != aciEvt->params.cmd_rsp.cmd_status) {
RedBearLab 0:075ea2812998 522 //ACI ReadDynamicData and ACI WriteDynamicData will have status codes of
RedBearLab 0:075ea2812998 523 //TRANSACTION_CONTINUE and TRANSACTION_COMPLETE
RedBearLab 0:075ea2812998 524 //all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command
RedBearLab 0:075ea2812998 525 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 526 Serial.print(F("ACI Command "));
RedBearLab 0:075ea2812998 527 Serial.println(aciEvt->params.cmd_rsp.cmd_opcode, HEX);
RedBearLab 0:075ea2812998 528 Serial.print(F("Evt Cmd respone: Status "));
RedBearLab 0:075ea2812998 529 Serial.println(aciEvt->params.cmd_rsp.cmd_status, HEX);
RedBearLab 0:075ea2812998 530 #endif
RedBearLab 0:075ea2812998 531 } else {
RedBearLab 0:075ea2812998 532 switch (aciEvt->params.cmd_rsp.cmd_opcode) {
RedBearLab 0:075ea2812998 533 case ACI_CMD_GET_DEVICE_VERSION:
RedBearLab 0:075ea2812998 534 break;
RedBearLab 0:075ea2812998 535
RedBearLab 0:075ea2812998 536 case ACI_CMD_GET_DEVICE_ADDRESS: {
RedBearLab 0:075ea2812998 537 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 538 char address[18];
RedBearLab 0:075ea2812998 539
RedBearLab 0:075ea2812998 540 sprintf(address, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
RedBearLab 0:075ea2812998 541 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[5],
RedBearLab 0:075ea2812998 542 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[4],
RedBearLab 0:075ea2812998 543 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[3],
RedBearLab 0:075ea2812998 544 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[2],
RedBearLab 0:075ea2812998 545 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[1],
RedBearLab 0:075ea2812998 546 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[0]);
RedBearLab 0:075ea2812998 547 Serial.print(F("Device address = "));
RedBearLab 0:075ea2812998 548 Serial.println(address);
RedBearLab 0:075ea2812998 549
RedBearLab 0:075ea2812998 550 Serial.print(F("Device address type = "));
RedBearLab 0:075ea2812998 551 Serial.println(aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_type, DEC);
RedBearLab 0:075ea2812998 552 #endif
RedBearLab 0:075ea2812998 553 if (this->_eventListener) {
RedBearLab 0:075ea2812998 554 this->_eventListener->nRF8001AddressReceived(*this, aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own);
RedBearLab 0:075ea2812998 555 }
RedBearLab 0:075ea2812998 556 break;
RedBearLab 0:075ea2812998 557 }
RedBearLab 0:075ea2812998 558
RedBearLab 0:075ea2812998 559 case ACI_CMD_GET_BATTERY_LEVEL: {
RedBearLab 0:075ea2812998 560 float batteryLevel = aciEvt->params.cmd_rsp.params.get_battery_level.battery_level * 0.00352;
RedBearLab 0:075ea2812998 561 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 562 Serial.print(F("Battery level = "));
RedBearLab 0:075ea2812998 563 Serial.println(batteryLevel);
RedBearLab 0:075ea2812998 564 #endif
RedBearLab 0:075ea2812998 565 if (this->_eventListener) {
RedBearLab 0:075ea2812998 566 this->_eventListener->nRF8001BatteryLevelReceived(*this, batteryLevel);
RedBearLab 0:075ea2812998 567 }
RedBearLab 0:075ea2812998 568 break;
RedBearLab 0:075ea2812998 569 }
RedBearLab 0:075ea2812998 570
RedBearLab 0:075ea2812998 571 case ACI_CMD_GET_TEMPERATURE: {
RedBearLab 0:075ea2812998 572 float temperature = aciEvt->params.cmd_rsp.params.get_temperature.temperature_value / 4.0;
RedBearLab 0:075ea2812998 573 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 574 Serial.print(F("Temperature = "));
RedBearLab 0:075ea2812998 575 Serial.println(temperature);
RedBearLab 0:075ea2812998 576 #endif
RedBearLab 0:075ea2812998 577 if (this->_eventListener) {
RedBearLab 0:075ea2812998 578 this->_eventListener->nRF8001TemperatureReceived(*this, temperature);
RedBearLab 0:075ea2812998 579 }
RedBearLab 0:075ea2812998 580 break;
RedBearLab 0:075ea2812998 581 }
RedBearLab 0:075ea2812998 582 }
RedBearLab 0:075ea2812998 583 }
RedBearLab 0:075ea2812998 584 break;
RedBearLab 0:075ea2812998 585
RedBearLab 0:075ea2812998 586 case ACI_EVT_CONNECTED:
RedBearLab 0:075ea2812998 587
RedBearLab 0:075ea2812998 588 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 589 char address[18];
RedBearLab 0:075ea2812998 590 sprintf(address, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
RedBearLab 0:075ea2812998 591 aciEvt->params.connected.dev_addr[5],
RedBearLab 0:075ea2812998 592 aciEvt->params.connected.dev_addr[4],
RedBearLab 0:075ea2812998 593 aciEvt->params.connected.dev_addr[3],
RedBearLab 0:075ea2812998 594 aciEvt->params.connected.dev_addr[2],
RedBearLab 0:075ea2812998 595 aciEvt->params.connected.dev_addr[1],
RedBearLab 0:075ea2812998 596 aciEvt->params.connected.dev_addr[0]);
RedBearLab 0:075ea2812998 597 Serial.print(F("Evt Connected "));
RedBearLab 0:075ea2812998 598 Serial.println(address);
RedBearLab 0:075ea2812998 599 #endif
RedBearLab 0:075ea2812998 600 if (this->_eventListener) {
RedBearLab 0:075ea2812998 601 this->_eventListener->nRF8001Connected(*this, aciEvt->params.connected.dev_addr);
RedBearLab 0:075ea2812998 602 }
RedBearLab 0:075ea2812998 603
RedBearLab 0:075ea2812998 604 this->_aciState.data_credit_available = this->_aciState.data_credit_total;
RedBearLab 0:075ea2812998 605 break;
RedBearLab 0:075ea2812998 606
RedBearLab 0:075ea2812998 607 case ACI_EVT_PIPE_STATUS:
RedBearLab 0:075ea2812998 608 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 609 Serial.println(F("Evt Pipe Status "));
RedBearLab 0:075ea2812998 610
RedBearLab 0:075ea2812998 611 uint64_t openPipes;
RedBearLab 0:075ea2812998 612 uint64_t closedPipes;
RedBearLab 0:075ea2812998 613
RedBearLab 0:075ea2812998 614 memcpy(&openPipes, aciEvt->params.pipe_status.pipes_open_bitmap, sizeof(openPipes));
RedBearLab 0:075ea2812998 615 memcpy(&closedPipes, aciEvt->params.pipe_status.pipes_closed_bitmap, sizeof(closedPipes));
RedBearLab 0:075ea2812998 616
RedBearLab 0:075ea2812998 617 Serial.println((unsigned long)openPipes, HEX);
RedBearLab 0:075ea2812998 618 Serial.println((unsigned long)closedPipes, HEX);
RedBearLab 0:075ea2812998 619 #endif
RedBearLab 0:075ea2812998 620
RedBearLab 0:075ea2812998 621 for (int i = 0; i < this->_numPipeInfo; i++) {
RedBearLab 0:075ea2812998 622 struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
RedBearLab 0:075ea2812998 623
RedBearLab 0:075ea2812998 624 if (pipeInfo->txPipe) {
RedBearLab 0:075ea2812998 625 pipeInfo->txPipeOpen = lib_aci_is_pipe_available(&this->_aciState, pipeInfo->txPipe);
RedBearLab 0:075ea2812998 626 }
RedBearLab 0:075ea2812998 627
RedBearLab 0:075ea2812998 628 if (pipeInfo->txAckPipe) {
RedBearLab 0:075ea2812998 629 pipeInfo->txAckPipeOpen = lib_aci_is_pipe_available(&this->_aciState, pipeInfo->txAckPipe);
RedBearLab 0:075ea2812998 630 }
RedBearLab 0:075ea2812998 631
RedBearLab 0:075ea2812998 632 bool subscribed = (pipeInfo->txPipeOpen || pipeInfo->txAckPipeOpen);
RedBearLab 0:075ea2812998 633
RedBearLab 0:075ea2812998 634 if (pipeInfo->characteristic->subscribed() != subscribed) {
RedBearLab 0:075ea2812998 635 if (this->_eventListener) {
RedBearLab 0:075ea2812998 636 this->_eventListener->nRF8001CharacteristicSubscribedChanged(*this, *pipeInfo->characteristic, subscribed);
RedBearLab 0:075ea2812998 637 }
RedBearLab 0:075ea2812998 638 }
RedBearLab 0:075ea2812998 639 }
RedBearLab 0:075ea2812998 640 break;
RedBearLab 0:075ea2812998 641
RedBearLab 0:075ea2812998 642 case ACI_EVT_TIMING:
RedBearLab 0:075ea2812998 643 break;
RedBearLab 0:075ea2812998 644
RedBearLab 0:075ea2812998 645 case ACI_EVT_DISCONNECTED:
RedBearLab 0:075ea2812998 646 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 647 Serial.println(F("Evt Disconnected/Advertising timed out"));
RedBearLab 0:075ea2812998 648 #endif
RedBearLab 0:075ea2812998 649 // all characteristics unsubscribed on disconnect
RedBearLab 0:075ea2812998 650 for (int i = 0; i < this->_numPipeInfo; i++) {
RedBearLab 0:075ea2812998 651 struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
RedBearLab 0:075ea2812998 652
RedBearLab 0:075ea2812998 653 if (pipeInfo->characteristic->subscribed()) {
RedBearLab 0:075ea2812998 654 if (this->_eventListener) {
RedBearLab 0:075ea2812998 655 this->_eventListener->nRF8001CharacteristicSubscribedChanged(*this, *pipeInfo->characteristic, false);
RedBearLab 0:075ea2812998 656 }
RedBearLab 0:075ea2812998 657 }
RedBearLab 0:075ea2812998 658 }
RedBearLab 0:075ea2812998 659
RedBearLab 0:075ea2812998 660 if (this->_eventListener) {
RedBearLab 0:075ea2812998 661 this->_eventListener->nRF8001Disconnected(*this);
RedBearLab 0:075ea2812998 662 }
RedBearLab 0:075ea2812998 663
RedBearLab 0:075ea2812998 664 lib_aci_connect(0/* in seconds : 0 means forever */, ADVERTISING_INTERVAL);
RedBearLab 0:075ea2812998 665 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 666 Serial.println(F("Advertising started."));
RedBearLab 0:075ea2812998 667 #endif
RedBearLab 0:075ea2812998 668 break;
RedBearLab 0:075ea2812998 669
RedBearLab 0:075ea2812998 670 case ACI_EVT_DATA_RECEIVED: {
RedBearLab 0:075ea2812998 671 uint8_t dataLen = aciEvt->len - 2;
RedBearLab 0:075ea2812998 672 uint8_t pipe = aciEvt->params.data_received.rx_data.pipe_number;
RedBearLab 0:075ea2812998 673 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 674 Serial.print(F("Data Received, pipe = "));
RedBearLab 0:075ea2812998 675 Serial.println(aciEvt->params.data_received.rx_data.pipe_number, DEC);
RedBearLab 0:075ea2812998 676
RedBearLab 0:075ea2812998 677 for (int i = 0; i < dataLen; i++) {
RedBearLab 0:075ea2812998 678 if ((aciEvt->params.data_received.rx_data.aci_data[i] & 0xf0) == 00) {
RedBearLab 0:075ea2812998 679 Serial.print("0");
RedBearLab 0:075ea2812998 680 }
RedBearLab 0:075ea2812998 681
RedBearLab 0:075ea2812998 682 Serial.print(aciEvt->params.data_received.rx_data.aci_data[i], HEX);
RedBearLab 0:075ea2812998 683 Serial.print(F(" "));
RedBearLab 0:075ea2812998 684 }
RedBearLab 0:075ea2812998 685 Serial.println();
RedBearLab 0:075ea2812998 686 #endif
RedBearLab 0:075ea2812998 687
RedBearLab 0:075ea2812998 688 for (int i = 0; i < this->_numPipeInfo; i++) {
RedBearLab 0:075ea2812998 689 struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
RedBearLab 0:075ea2812998 690
RedBearLab 0:075ea2812998 691 if (pipeInfo->rxAckPipe == pipe || pipeInfo->rxPipe == pipe) {
RedBearLab 0:075ea2812998 692 if (pipeInfo->rxAckPipe == pipe) {
RedBearLab 0:075ea2812998 693 lib_aci_send_ack(&this->_aciState, pipeInfo->rxAckPipe);
RedBearLab 0:075ea2812998 694 }
RedBearLab 0:075ea2812998 695
RedBearLab 0:075ea2812998 696 if (this->_eventListener) {
RedBearLab 0:075ea2812998 697 this->_eventListener->nRF8001CharacteristicValueChanged(*this, *pipeInfo->characteristic, aciEvt->params.data_received.rx_data.aci_data, dataLen);
RedBearLab 0:075ea2812998 698 }
RedBearLab 0:075ea2812998 699 break;
RedBearLab 0:075ea2812998 700 }
RedBearLab 0:075ea2812998 701 }
RedBearLab 0:075ea2812998 702 }
RedBearLab 0:075ea2812998 703 break;
RedBearLab 0:075ea2812998 704
RedBearLab 0:075ea2812998 705 case ACI_EVT_DATA_CREDIT:
RedBearLab 0:075ea2812998 706 this->_aciState.data_credit_available = this->_aciState.data_credit_available + aciEvt->params.data_credit.credit;
RedBearLab 0:075ea2812998 707 break;
RedBearLab 0:075ea2812998 708
RedBearLab 0:075ea2812998 709 case ACI_EVT_PIPE_ERROR:
RedBearLab 0:075ea2812998 710 //See the appendix in the nRF8001 Product Specication for details on the error codes
RedBearLab 0:075ea2812998 711 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 712 Serial.print(F("ACI Evt Pipe Error: Pipe #:"));
RedBearLab 0:075ea2812998 713 Serial.print(aciEvt->params.pipe_error.pipe_number, DEC);
RedBearLab 0:075ea2812998 714 Serial.print(F(" Pipe Error Code: 0x"));
RedBearLab 0:075ea2812998 715 Serial.println(aciEvt->params.pipe_error.error_code, HEX);
RedBearLab 0:075ea2812998 716 #endif
RedBearLab 0:075ea2812998 717
RedBearLab 0:075ea2812998 718 //Increment the credit available as the data packet was not sent.
RedBearLab 0:075ea2812998 719 //The pipe error also represents the Attribute protocol Error Response sent from the peer and that should not be counted
RedBearLab 0:075ea2812998 720 //for the credit.
RedBearLab 0:075ea2812998 721 if (ACI_STATUS_ERROR_PEER_ATT_ERROR != aciEvt->params.pipe_error.error_code) {
RedBearLab 0:075ea2812998 722 this->_aciState.data_credit_available++;
RedBearLab 0:075ea2812998 723 }
RedBearLab 0:075ea2812998 724 break;
RedBearLab 0:075ea2812998 725
RedBearLab 0:075ea2812998 726 case ACI_EVT_HW_ERROR:
RedBearLab 0:075ea2812998 727 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 728 Serial.print(F("HW error: "));
RedBearLab 0:075ea2812998 729 Serial.println(aciEvt->params.hw_error.line_num, DEC);
RedBearLab 0:075ea2812998 730
RedBearLab 0:075ea2812998 731 for(uint8_t counter = 0; counter <= (aciEvt->len - 3); counter++) {
RedBearLab 0:075ea2812998 732 Serial.write(aciEvt->params.hw_error.file_name[counter]); //uint8_t file_name[20];
RedBearLab 0:075ea2812998 733 }
RedBearLab 0:075ea2812998 734 Serial.println();
RedBearLab 0:075ea2812998 735 #endif
RedBearLab 0:075ea2812998 736 lib_aci_connect(0/* in seconds, 0 means forever */, ADVERTISING_INTERVAL);
RedBearLab 0:075ea2812998 737 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 738 Serial.println(F("Advertising started."));
RedBearLab 0:075ea2812998 739 #endif
RedBearLab 0:075ea2812998 740 break;
RedBearLab 0:075ea2812998 741 }
RedBearLab 0:075ea2812998 742 } else {
RedBearLab 0:075ea2812998 743 //Serial.println(F("No ACI Events available"));
RedBearLab 0:075ea2812998 744 // No event in the ACI Event queue and if there is no event in the ACI command queue the arduino can go to sleep
RedBearLab 0:075ea2812998 745 // Arduino can go to sleep now
RedBearLab 0:075ea2812998 746 // Wakeup from sleep from the RDYN line
RedBearLab 0:075ea2812998 747 }
RedBearLab 0:075ea2812998 748 }
RedBearLab 0:075ea2812998 749
RedBearLab 0:075ea2812998 750 bool nRF8001::updateCharacteristicValue(BLECharacteristic& characteristic) {
RedBearLab 0:075ea2812998 751 bool success = true;
RedBearLab 0:075ea2812998 752
RedBearLab 0:075ea2812998 753 for (int i = 0; i < this->_numPipeInfo; i++) {
RedBearLab 0:075ea2812998 754 struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
RedBearLab 0:075ea2812998 755
RedBearLab 0:075ea2812998 756 if (pipeInfo->characteristic == &characteristic) {
RedBearLab 0:075ea2812998 757 if (pipeInfo->setPipe) {
RedBearLab 0:075ea2812998 758 success &= lib_aci_set_local_data(&this->_aciState, pipeInfo->setPipe, (uint8_t*)characteristic.value(), characteristic.valueLength());
RedBearLab 0:075ea2812998 759 }
RedBearLab 0:075ea2812998 760
RedBearLab 0:075ea2812998 761 if (pipeInfo->txPipe && pipeInfo->txPipeOpen) {
RedBearLab 0:075ea2812998 762 if (this->canNotifyCharacteristic(characteristic)) {
RedBearLab 0:075ea2812998 763 this->_aciState.data_credit_available--;
RedBearLab 0:075ea2812998 764 success &= lib_aci_send_data(pipeInfo->txPipe, (uint8_t*)characteristic.value(), characteristic.valueLength());
RedBearLab 0:075ea2812998 765 } else {
RedBearLab 0:075ea2812998 766 success = false;
RedBearLab 0:075ea2812998 767 }
RedBearLab 0:075ea2812998 768 }
RedBearLab 0:075ea2812998 769
RedBearLab 0:075ea2812998 770 if (pipeInfo->txAckPipe && pipeInfo->txAckPipeOpen) {
RedBearLab 0:075ea2812998 771 if (this->canIndicateCharacteristic(characteristic)) {
RedBearLab 0:075ea2812998 772 this->_aciState.data_credit_available--;
RedBearLab 0:075ea2812998 773 success &= lib_aci_send_data(pipeInfo->txAckPipe, (uint8_t*)characteristic.value(), characteristic.valueLength());
RedBearLab 0:075ea2812998 774 } else {
RedBearLab 0:075ea2812998 775 success = false;
RedBearLab 0:075ea2812998 776 }
RedBearLab 0:075ea2812998 777 }
RedBearLab 0:075ea2812998 778
RedBearLab 0:075ea2812998 779 break;
RedBearLab 0:075ea2812998 780 }
RedBearLab 0:075ea2812998 781 }
RedBearLab 0:075ea2812998 782
RedBearLab 0:075ea2812998 783 return success;
RedBearLab 0:075ea2812998 784 }
RedBearLab 0:075ea2812998 785
RedBearLab 0:075ea2812998 786 bool nRF8001::canNotifyCharacteristic(BLECharacteristic& characteristic) {
RedBearLab 0:075ea2812998 787 return (lib_aci_get_nb_available_credits(&this->_aciState) > 0);
RedBearLab 0:075ea2812998 788 }
RedBearLab 0:075ea2812998 789
RedBearLab 0:075ea2812998 790 bool nRF8001::canIndicateCharacteristic(BLECharacteristic& characteristic) {
RedBearLab 0:075ea2812998 791 return (lib_aci_get_nb_available_credits(&this->_aciState) > 0);
RedBearLab 0:075ea2812998 792 }
RedBearLab 0:075ea2812998 793
RedBearLab 0:075ea2812998 794 void nRF8001::disconnect() {
RedBearLab 0:075ea2812998 795 lib_aci_disconnect(&this->_aciState, ACI_REASON_TERMINATE);
RedBearLab 0:075ea2812998 796 }
RedBearLab 0:075ea2812998 797 void nRF8001::requestAddress() {
RedBearLab 0:075ea2812998 798 lib_aci_get_address();
RedBearLab 0:075ea2812998 799 }
RedBearLab 0:075ea2812998 800
RedBearLab 0:075ea2812998 801 void nRF8001::requestTemperature() {
RedBearLab 0:075ea2812998 802 lib_aci_get_temperature();
RedBearLab 0:075ea2812998 803 }
RedBearLab 0:075ea2812998 804
RedBearLab 0:075ea2812998 805 void nRF8001::requestBatteryLevel() {
RedBearLab 0:075ea2812998 806 lib_aci_get_battery_level();
RedBearLab 0:075ea2812998 807 }
RedBearLab 0:075ea2812998 808
RedBearLab 0:075ea2812998 809 void nRF8001::waitForSetupMode()
RedBearLab 0:075ea2812998 810 {
RedBearLab 0:075ea2812998 811 bool setupMode = false;
RedBearLab 0:075ea2812998 812
RedBearLab 0:075ea2812998 813 while (!setupMode) {
RedBearLab 0:075ea2812998 814 if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
RedBearLab 0:075ea2812998 815 aci_evt_t* aciEvt = &this->_aciData.evt;
RedBearLab 0:075ea2812998 816
RedBearLab 0:075ea2812998 817 switch(aciEvt->evt_opcode) {
RedBearLab 0:075ea2812998 818 case ACI_EVT_DEVICE_STARTED: {
RedBearLab 0:075ea2812998 819 switch(aciEvt->params.device_started.device_mode) {
RedBearLab 0:075ea2812998 820 case ACI_DEVICE_SETUP:
RedBearLab 0:075ea2812998 821 /**
RedBearLab 0:075ea2812998 822 When the device is in the setup mode
RedBearLab 0:075ea2812998 823 */
RedBearLab 0:075ea2812998 824 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 825 Serial.println(F("Evt Device Started: Setup"));
RedBearLab 0:075ea2812998 826 #endif
RedBearLab 0:075ea2812998 827 setupMode = true;
RedBearLab 0:075ea2812998 828 break;
RedBearLab 0:075ea2812998 829 }
RedBearLab 0:075ea2812998 830 }
RedBearLab 0:075ea2812998 831 }
RedBearLab 0:075ea2812998 832 } else {
RedBearLab 0:075ea2812998 833 delay(1);
RedBearLab 0:075ea2812998 834 }
RedBearLab 0:075ea2812998 835 }
RedBearLab 0:075ea2812998 836 }
RedBearLab 0:075ea2812998 837
RedBearLab 0:075ea2812998 838 void nRF8001::sendSetupMessage(hal_aci_data_t* data)
RedBearLab 0:075ea2812998 839 {
RedBearLab 0:075ea2812998 840 this->_crcSeed = crc_16_ccitt(this->_crcSeed, data->buffer, data->buffer[0] + 1);
RedBearLab 0:075ea2812998 841
RedBearLab 0:075ea2812998 842 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 843 for (int j = 0; j < (data->buffer[0] + 1); j++) {
RedBearLab 0:075ea2812998 844 if ((data->buffer[j] & 0xf0) == 00) {
RedBearLab 0:075ea2812998 845 Serial.print("0");
RedBearLab 0:075ea2812998 846 }
RedBearLab 0:075ea2812998 847
RedBearLab 0:075ea2812998 848 Serial.print(data->buffer[j], HEX);
RedBearLab 0:075ea2812998 849 Serial.print(" ");
RedBearLab 0:075ea2812998 850 }
RedBearLab 0:075ea2812998 851 Serial.println();
RedBearLab 0:075ea2812998 852 #endif
RedBearLab 0:075ea2812998 853
RedBearLab 0:075ea2812998 854 hal_aci_tl_send(data);
RedBearLab 0:075ea2812998 855
RedBearLab 0:075ea2812998 856 bool setupMsgSent = false;
RedBearLab 0:075ea2812998 857
RedBearLab 0:075ea2812998 858 while (!setupMsgSent) {
RedBearLab 0:075ea2812998 859 if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
RedBearLab 0:075ea2812998 860 aci_evt_t* aciEvt = &this->_aciData.evt;
RedBearLab 0:075ea2812998 861
RedBearLab 0:075ea2812998 862 switch(aciEvt->evt_opcode) {
RedBearLab 0:075ea2812998 863 case ACI_EVT_CMD_RSP: {
RedBearLab 0:075ea2812998 864 switch(aciEvt->params.cmd_rsp.cmd_status) {
RedBearLab 0:075ea2812998 865 case ACI_STATUS_TRANSACTION_CONTINUE:
RedBearLab 0:075ea2812998 866 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 867 Serial.println(F("Evt Cmd Rsp: Transaction Continue"));
RedBearLab 0:075ea2812998 868 #endif
RedBearLab 0:075ea2812998 869 setupMsgSent = true;
RedBearLab 0:075ea2812998 870 break;
RedBearLab 0:075ea2812998 871 }
RedBearLab 0:075ea2812998 872 }
RedBearLab 0:075ea2812998 873 }
RedBearLab 0:075ea2812998 874 } else {
RedBearLab 0:075ea2812998 875 delay(1);
RedBearLab 0:075ea2812998 876 }
RedBearLab 0:075ea2812998 877 }
RedBearLab 0:075ea2812998 878 }
RedBearLab 0:075ea2812998 879
RedBearLab 0:075ea2812998 880 void nRF8001::sendCrc()
RedBearLab 0:075ea2812998 881 {
RedBearLab 0:075ea2812998 882 hal_aci_data_t data;
RedBearLab 0:075ea2812998 883 data.status_byte = 0;
RedBearLab 0:075ea2812998 884
RedBearLab 0:075ea2812998 885 data.buffer[0] = 3 + 3;
RedBearLab 0:075ea2812998 886 data.buffer[1] = ACI_CMD_SETUP;
RedBearLab 0:075ea2812998 887 data.buffer[2] = 0xf0;
RedBearLab 0:075ea2812998 888 data.buffer[3] = 0x00;
RedBearLab 0:075ea2812998 889
RedBearLab 0:075ea2812998 890 data.buffer[4] = 0x03;
RedBearLab 0:075ea2812998 891
RedBearLab 0:075ea2812998 892 this->_crcSeed = crc_16_ccitt(this->_crcSeed, data.buffer, data.buffer[0] - 1);
RedBearLab 0:075ea2812998 893
RedBearLab 0:075ea2812998 894 data.buffer[5] = (this->_crcSeed >> 8) & 0xff;
RedBearLab 0:075ea2812998 895 data.buffer[6] = this->_crcSeed & 0xff;
RedBearLab 0:075ea2812998 896
RedBearLab 0:075ea2812998 897 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 898 for (int j = 0; j < (data.buffer[0] + 1); j++) {
RedBearLab 0:075ea2812998 899 if ((data.buffer[j] & 0xf0) == 00) {
RedBearLab 0:075ea2812998 900 Serial.print("0");
RedBearLab 0:075ea2812998 901 }
RedBearLab 0:075ea2812998 902
RedBearLab 0:075ea2812998 903 Serial.print(data.buffer[j], HEX);
RedBearLab 0:075ea2812998 904 Serial.print(" ");
RedBearLab 0:075ea2812998 905 }
RedBearLab 0:075ea2812998 906 Serial.println();
RedBearLab 0:075ea2812998 907 #endif
RedBearLab 0:075ea2812998 908
RedBearLab 0:075ea2812998 909 hal_aci_tl_send(&data);
RedBearLab 0:075ea2812998 910
RedBearLab 0:075ea2812998 911 bool setupMsgSent = false;
RedBearLab 0:075ea2812998 912
RedBearLab 0:075ea2812998 913 while (!setupMsgSent) {
RedBearLab 0:075ea2812998 914 if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
RedBearLab 0:075ea2812998 915 aci_evt_t* aciEvt = &this->_aciData.evt;
RedBearLab 0:075ea2812998 916
RedBearLab 0:075ea2812998 917 switch(aciEvt->evt_opcode) {
RedBearLab 0:075ea2812998 918 case ACI_EVT_CMD_RSP: {
RedBearLab 0:075ea2812998 919 switch(aciEvt->params.cmd_rsp.cmd_status) {
RedBearLab 0:075ea2812998 920 case ACI_STATUS_TRANSACTION_COMPLETE:
RedBearLab 0:075ea2812998 921 #ifdef NRF_8001_DEBUG
RedBearLab 0:075ea2812998 922 Serial.println(F("Evt Cmd Rsp: Transaction Complete"));
RedBearLab 0:075ea2812998 923 #endif
RedBearLab 0:075ea2812998 924 setupMsgSent = true;
RedBearLab 0:075ea2812998 925 break;
RedBearLab 0:075ea2812998 926 }
RedBearLab 0:075ea2812998 927 }
RedBearLab 0:075ea2812998 928 }
RedBearLab 0:075ea2812998 929 } else {
RedBearLab 0:075ea2812998 930 delay(1);
RedBearLab 0:075ea2812998 931 }
RedBearLab 0:075ea2812998 932 }
RedBearLab 0:075ea2812998 933 }