added debugging

Fork of BLE_nRF8001 by RedBearLab

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nRF8001.cpp Source File

nRF8001.cpp

00001 
00002 #include "BLEAttribute.h"
00003 #include "BLEService.h"
00004 #include "BLECharacteristic.h"
00005 #include "BLEDescriptor.h"
00006 #include "BLEUuid.h"
00007 
00008 #include "nRF8001.h"
00009 
00010 //#define NRF_8001_DEBUG
00011 
00012 #define ADVERTISING_INTERVAL 0x050
00013 
00014 struct setupMsgData {
00015   unsigned char length;
00016   unsigned char cmd;
00017   unsigned char type;
00018   unsigned char offset;
00019   unsigned char data[28];
00020 };
00021 
00022 #define NB_BASE_SETUP_MESSAGES 7
00023 
00024 /* Store the setup for the nRF8001 in the flash of the AVR to save on RAM */
00025 static hal_aci_data_t baseSetupMsgs[NB_BASE_SETUP_MESSAGES] PROGMEM = {\
00026   {0x00,\
00027     {\
00028       0x07,0x06,0x00,0x00,0x03,0x02,0x41,0xfe,\
00029     },\
00030   },\
00031   {0x00,\
00032     {\
00033       0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x06,0x00,0x06,\
00034       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
00035     },\
00036   },\
00037   {0x00,\
00038     {\
00039       0x1f,0x06,0x10,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
00040       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x90,0x00,0xff,\
00041     },\
00042   },\
00043   {0x00,\
00044     {\
00045       0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
00046       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,\
00047     },\
00048   },\
00049   {0x00,\
00050     {\
00051       0x05,0x06,0x10,0x54,0x00,0x02,\
00052     },\
00053   },\
00054   {0x00,\
00055     {\
00056       0x19,0x06,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
00057       0x00,0x00,0x00,0x00,0x00,0x00,\
00058     },\
00059   },\
00060   {0x00,\
00061     {\
00062       0x19,0x06,0x70,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
00063       0x00,0x00,0x00,0x00,0x00,0x00,\
00064     },\
00065   },\
00066 };
00067 
00068 void __ble_assert(const char *file, uint16_t line)
00069 {
00070   serial.printf("ERROR ");
00071   serial.printf(file);
00072   serial.printf(": ");
00073   serial.printf("%d\n",line);
00074   while(1);
00075 }
00076 
00077 /** crc function to re-calulate the CRC after making changes to the setup data.
00078 */
00079 uint16_t crc_16_ccitt(uint16_t crc, uint8_t * data_in, uint16_t data_len) {
00080 
00081   uint16_t i;
00082 
00083   for(i = 0; i < data_len; i++)
00084   {
00085     crc  = (unsigned char)(crc >> 8) | (crc << 8);
00086     crc ^= data_in[i];
00087     crc ^= (unsigned char)(crc & 0xff) >> 4;
00088     crc ^= (crc << 8) << 4;
00089     crc ^= ((crc & 0xff) << 4) << 1;
00090   }
00091 
00092   return crc;
00093 }
00094 
00095 nRF8001::nRF8001(DigitalInOut *req, DigitalInOut *rdy, DigitalInOut *rst) :
00096   _pipeInfo(NULL),
00097   _numPipeInfo(0),
00098 
00099   _crcSeed(0xFFFF),
00100 
00101   _eventListener(NULL)
00102 {
00103   this->_aciState.aci_pins.reqn_pin               = req;
00104   this->_aciState.aci_pins.rdyn_pin               = rdy;
00105 
00106   if (rst == NULL) {
00107     this->_aciState.aci_pins.board_name           = REDBEARLAB_SHIELD_V1_1;
00108   } 
00109   else {
00110     this->_aciState.aci_pins.board_name           = BOARD_DEFAULT;
00111   }
00112 
00113   this->_aciState.aci_pins.reset_pin              = rst;
00114   this->_aciState.aci_pins.active_pin             = NULL;
00115 
00116   this->_aciState.aci_pins.interface_is_interrupt = false;
00117   this->_aciState.aci_pins.interrupt_number       = 1;
00118 }
00119 
00120 nRF8001::~nRF8001() {
00121   if (this->_pipeInfo) {
00122     free(this->_pipeInfo);
00123   }
00124 }
00125 
00126 
00127 
00128 void nRF8001::setEventListener(nRF8001EventListener* eventListener) {
00129   this->_eventListener = eventListener;
00130 }
00131 
00132 void nRF8001::begin(const unsigned char* advertisementData,
00133                       unsigned char advertisementDataLength,
00134                       const unsigned char* scanData,
00135                       unsigned char scanDataLength,
00136                       BLEAttribute** attributes,
00137                       unsigned char numAttributes)
00138 {
00139   unsigned char numPipedCharacteristics = 0;
00140 
00141   for (int i = 0; i < numAttributes; i++) {
00142     BLEAttribute* attribute = attributes[i];
00143 
00144     if (attribute->type() == BLETypeCharacteristic) {
00145       BLECharacteristic* characteristic = (BLECharacteristic *)attribute;
00146 
00147       if (characteristic->properties()) {
00148         numPipedCharacteristics++;
00149       }
00150     }
00151   }
00152 
00153   this->_pipeInfo = (struct pipeInfo*)malloc(sizeof(struct pipeInfo) * numPipedCharacteristics);
00154 
00155   lib_aci_init(&this->_aciState, false);
00156 
00157   this->waitForSetupMode();
00158 
00159   hal_aci_data_t setupMsg;
00160   struct setupMsgData* setupMsgData = (struct setupMsgData*)setupMsg.buffer;
00161 
00162   setupMsg.status_byte = 0;
00163 
00164   for (int i = 0; i < NB_BASE_SETUP_MESSAGES; i++) {
00165     int setupMsgSize = pgm_read_byte_near(&baseSetupMsgs[i].buffer[0]) + 2;
00166 
00167     memcpy_P(&setupMsg, &baseSetupMsgs[i], setupMsgSize);
00168 
00169     if (i == 1) {
00170       setupMsgData->data[6] = numPipedCharacteristics;
00171       setupMsgData->data[8] = numPipedCharacteristics;
00172     } else if (i == 2 && advertisementData && advertisementDataLength) {
00173       setupMsgData->data[22] = 0x40;
00174     } else if (i == 3 && scanData && scanDataLength) {
00175       setupMsgData->data[12] = 0x40;
00176     } else if (i == 5 && advertisementData && advertisementDataLength) {
00177       memcpy(setupMsgData->data, advertisementData, advertisementDataLength);
00178     } else if (i == 6 && scanData && scanDataLength) {
00179       memcpy(setupMsgData->data, scanData, scanDataLength);
00180     }
00181 
00182     this->sendSetupMessage(&setupMsg);
00183   }
00184 
00185   // GATT
00186   unsigned char  gattSetupMsgOffset = 0;
00187   unsigned short handle             = 1;
00188   unsigned char  pipe               = 1;
00189   unsigned char  numPiped           = 0;
00190 
00191   for (int i = 0; i < numAttributes; i++) {
00192     BLEAttribute* attribute = attributes[i];
00193     BLEUuid uuid = BLEUuid(attribute->uuid());
00194 
00195     if (attribute->type() == BLETypeService) {
00196       BLEService* service = (BLEService *)attribute;
00197 
00198       setupMsgData->length  = 12 + uuid.length();
00199       setupMsgData->cmd     = ACI_CMD_SETUP;
00200       setupMsgData->type    = 0x20;
00201       setupMsgData->offset  = gattSetupMsgOffset;
00202 
00203       setupMsgData->data[0] = 0x04;
00204       setupMsgData->data[1] = 0x04;
00205       setupMsgData->data[2] = uuid.length();
00206       setupMsgData->data[3] = uuid.length();
00207 
00208       setupMsgData->data[4] = (handle >> 8) & 0xff;
00209       setupMsgData->data[5] = handle & 0xff;
00210       handle++;
00211 
00212       setupMsgData->data[6] = (service->type() >> 8) & 0xff;
00213       setupMsgData->data[7] = service->type() & 0xff;
00214 
00215       setupMsgData->data[8] = ACI_STORE_LOCAL;
00216 
00217       memcpy(&setupMsgData->data[9], uuid.data(), uuid.length());
00218 
00219       gattSetupMsgOffset += 9 + uuid.length();
00220 
00221       this->sendSetupMessage(&setupMsg);
00222     } else if (attribute->type() == BLETypeCharacteristic) {
00223       BLECharacteristic* characteristic = (BLECharacteristic *)attribute;
00224 
00225       struct pipeInfo* pipeInfo = &this->_pipeInfo[numPiped];
00226 
00227       memset(pipeInfo, 0, sizeof(struct pipeInfo));
00228 
00229       pipeInfo->characteristic = characteristic;
00230 
00231       if (characteristic->properties()) {
00232         numPiped++;
00233 
00234         pipeInfo->startPipe = pipe;
00235 
00236         if (characteristic->properties() & BLENotify) {
00237           pipeInfo->txPipe = pipe;
00238 
00239           pipe++;
00240         }
00241 
00242         if (characteristic->properties() & BLEIndicate) {
00243           pipeInfo->txAckPipe = pipe;
00244 
00245           pipe++;
00246         }
00247 
00248         if (characteristic->properties() & BLEWriteWithoutResponse) {
00249           pipeInfo->rxPipe = pipe;
00250 
00251           pipe++;
00252         }
00253 
00254         if (characteristic->properties() & BLEWrite) {
00255           pipeInfo->rxAckPipe = pipe;
00256 
00257           pipe++;
00258         }
00259 
00260         if (characteristic->properties() & BLERead) {
00261           pipeInfo->setPipe = pipe;
00262 
00263           pipe++;
00264         }
00265       }
00266 
00267       setupMsgData->length   = 15 + uuid.length();
00268       setupMsgData->cmd      = ACI_CMD_SETUP;
00269       setupMsgData->type     = 0x20;
00270       setupMsgData->offset   = gattSetupMsgOffset;
00271 
00272       setupMsgData->data[0]  = 0x04;
00273       setupMsgData->data[1]  = 0x04;
00274       setupMsgData->data[2]  = 3 + uuid.length();
00275       setupMsgData->data[3]  = 3 + uuid.length();
00276 
00277       setupMsgData->data[4]  = (handle >> 8) & 0xff;
00278       setupMsgData->data[5]  = handle & 0xff;
00279       handle++;
00280 
00281       setupMsgData->data[6]  = (characteristic->type() >> 8) & 0xff;
00282       setupMsgData->data[7]  = characteristic->type() & 0xff;
00283 
00284       setupMsgData->data[8]  = ACI_STORE_LOCAL;
00285       setupMsgData->data[9]  = characteristic->properties();
00286 
00287       setupMsgData->data[10] = handle & 0xff;
00288       setupMsgData->data[11] = (handle >> 8) & 0xff;
00289       pipeInfo->valueHandle = handle;
00290       handle++;
00291 
00292       memcpy(&setupMsgData->data[12], uuid.data(), uuid.length());
00293 
00294       gattSetupMsgOffset += 12 + uuid.length();
00295 
00296       this->sendSetupMessage(&setupMsg);
00297 
00298       setupMsgData->length   = 12 + characteristic->valueSize();
00299       setupMsgData->cmd      = ACI_CMD_SETUP;
00300       setupMsgData->type     = 0x20;
00301       setupMsgData->offset   = gattSetupMsgOffset;
00302 
00303       setupMsgData->data[0]  = 0x04;
00304       setupMsgData->data[1]  = 0x00;
00305 
00306       if (characteristic->fixedLength()) {
00307         setupMsgData->data[0] |= 0x02;
00308       }
00309 
00310       if (characteristic->properties() & BLERead) {
00311         setupMsgData->data[1] |= 0x04;
00312       }
00313 
00314       if (characteristic->properties() & (BLEWrite | BLEWriteWithoutResponse)) {
00315         setupMsgData->data[0] |= 0x40;
00316         setupMsgData->data[1] |= 0x10;
00317       }
00318 
00319       if (characteristic->properties() & BLENotify) {
00320         setupMsgData->data[0] |= 0x10;
00321       }
00322 
00323       if (characteristic->properties() & BLEIndicate) {
00324         setupMsgData->data[0] |= 0x20;
00325       }
00326 
00327       setupMsgData->data[2]  = characteristic->valueSize();
00328       if (characteristic->fixedLength()) {
00329         setupMsgData->data[2]++;
00330       }
00331 
00332       setupMsgData->data[3]  = characteristic->valueLength();
00333 
00334       setupMsgData->data[4]  = (pipeInfo->valueHandle >> 8) & 0xff;
00335       setupMsgData->data[5]  = pipeInfo->valueHandle & 0xff;
00336 
00337       setupMsgData->data[6]  = 0x00;
00338       setupMsgData->data[7]  = 0x00;
00339 
00340       setupMsgData->data[8]  = 0x02;
00341 
00342       memset(&setupMsgData->data[9], 0x00, characteristic->valueSize());
00343       memcpy(&setupMsgData->data[9], characteristic->value(), characteristic->valueLength());
00344 
00345       gattSetupMsgOffset += 9 + characteristic->valueSize();
00346 
00347       this->sendSetupMessage(&setupMsg);
00348 
00349       if (characteristic->properties() & (BLENotify | BLEIndicate)) {
00350         setupMsgData->length   = 14;
00351         setupMsgData->cmd      = ACI_CMD_SETUP;
00352         setupMsgData->type     = 0x20;
00353         setupMsgData->offset   = gattSetupMsgOffset;
00354 
00355         setupMsgData->data[0]  = 0x46;
00356         setupMsgData->data[1]  = 0x14;
00357 
00358         setupMsgData->data[2]  = 0x03;
00359         setupMsgData->data[3]  = 0x02;
00360 
00361         setupMsgData->data[4]  = (handle >> 8) & 0xff;
00362         setupMsgData->data[5]  = handle & 0xff;
00363         pipeInfo->configHandle = handle;
00364         handle++;
00365 
00366         setupMsgData->data[6]  = 0x29;
00367         setupMsgData->data[7]  = 0x02;
00368 
00369         setupMsgData->data[8]  = ACI_STORE_LOCAL;
00370 
00371         setupMsgData->data[9]  = 0x00;
00372         setupMsgData->data[10] = 0x00;
00373 
00374         gattSetupMsgOffset += 11;
00375 
00376         this->sendSetupMessage(&setupMsg);
00377       }
00378     } else if (attribute->type() == BLETypeDescriptor) {
00379       BLEDescriptor* descriptor = (BLEDescriptor *)attribute;
00380 
00381       setupMsgData->length   = 12 + descriptor->valueSize();
00382       setupMsgData->cmd      = ACI_CMD_SETUP;
00383       setupMsgData->type     = 0x20;
00384       setupMsgData->offset   = gattSetupMsgOffset;
00385 
00386       setupMsgData->data[0]  = 0x04;
00387       setupMsgData->data[1]  = 0x04;
00388 
00389       setupMsgData->data[2]  = descriptor->valueSize();
00390       setupMsgData->data[3]  = descriptor->valueLength();
00391 
00392       setupMsgData->data[4]  = (handle >> 8) & 0xff;
00393       setupMsgData->data[5]  = handle & 0xff;
00394       handle++;
00395 
00396       setupMsgData->data[6]  = uuid.data()[1];
00397       setupMsgData->data[7]  = uuid.data()[0];
00398 
00399       setupMsgData->data[8]  = ACI_STORE_LOCAL;
00400 
00401       memcpy(&setupMsgData->data[9], descriptor->value(), descriptor->valueLength());
00402 
00403       gattSetupMsgOffset += 9 + descriptor->valueSize();
00404 
00405       this->sendSetupMessage(&setupMsg);
00406     }
00407   }
00408 
00409   this->_numPipeInfo = numPiped;
00410 
00411   // terminator
00412   setupMsgData->length   = 4;
00413   setupMsgData->cmd      = ACI_CMD_SETUP;
00414   setupMsgData->type     = 0x20;
00415   setupMsgData->offset   = gattSetupMsgOffset;
00416 
00417   setupMsgData->data[0]  = 0x00;
00418 
00419   gattSetupMsgOffset += 6;
00420 
00421   this->sendSetupMessage(&setupMsg);
00422 
00423   // pipes
00424   unsigned char pipeSetupMsgOffet  = 0;
00425 
00426   for (int i = 0; i < numPiped; i++) {
00427     struct pipeInfo pipeInfo = this->_pipeInfo[i];
00428 
00429     setupMsgData->length   = 13;
00430     setupMsgData->cmd      = ACI_CMD_SETUP;
00431     setupMsgData->type     = 0x40;
00432     setupMsgData->offset   = pipeSetupMsgOffet;
00433 
00434     setupMsgData->data[0]  = 0x00;
00435     setupMsgData->data[1]  = 0x00;
00436 
00437     setupMsgData->data[2]  = pipeInfo.startPipe;
00438 
00439     setupMsgData->data[3]  = 0x00;
00440     setupMsgData->data[4]  = 0x00;
00441 
00442     setupMsgData->data[5]  = 0x04;
00443 
00444     setupMsgData->data[6]  = (pipeInfo.valueHandle >> 8) & 0xff;
00445     setupMsgData->data[7]  = pipeInfo.valueHandle & 0xff;
00446 
00447     setupMsgData->data[8]  = (pipeInfo.configHandle >> 8) & 0xff;
00448     setupMsgData->data[9]  = pipeInfo.configHandle & 0xff;
00449 
00450     if (pipeInfo.characteristic->properties() & BLEIndicate) {
00451       setupMsgData->data[4] |= 0x04; // TX Ack
00452     }
00453 
00454     if (pipeInfo.characteristic->properties() & BLENotify) {
00455       setupMsgData->data[4] |= 0x02; // TX
00456     }
00457 
00458     if (pipeInfo.characteristic->properties() & BLEWriteWithoutResponse) {
00459       setupMsgData->data[4] |= 0x08; // RX Ack
00460     }
00461 
00462     if (pipeInfo.characteristic->properties() & BLEWrite) {
00463       setupMsgData->data[4] |= 0x10; // RX Ack
00464     }
00465 
00466     if (pipeInfo.characteristic->properties() & BLERead) {
00467       setupMsgData->data[4] |= 0x80; // Set
00468     }
00469 
00470     pipeSetupMsgOffet += 10;
00471 
00472     this->sendSetupMessage(&setupMsg);
00473   }
00474 
00475   this->sendCrc();
00476 }
00477 
00478 void nRF8001::poll() {
00479   // We enter the if statement only when there is a ACI event available to be processed
00480   if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
00481     aci_evt_t* aciEvt;
00482     aciEvt = &this->_aciData.evt;
00483 
00484     switch(aciEvt->evt_opcode) {
00485       /**
00486       As soon as you reset the nRF8001 you will get an ACI Device Started Event
00487       */
00488       case ACI_EVT_DEVICE_STARTED: {
00489         this->_aciState.data_credit_total = aciEvt->params.device_started.credit_available;
00490         switch(aciEvt->params.device_started.device_mode) {
00491           case ACI_DEVICE_SETUP:
00492             /**
00493             When the device is in the setup mode
00494             */
00495 #ifdef NRF_8001_DEBUG
00496             Serial.println(F("Evt Device Started: Setup"));
00497 #endif
00498             break;
00499 
00500           case ACI_DEVICE_STANDBY:
00501 #ifdef NRF_8001_DEBUG
00502             Serial.println(F("Evt Device Started: Standby"));
00503 #endif
00504             //Looking for an iPhone by sending radio advertisements
00505             //When an iPhone connects to us we will get an ACI_EVT_CONNECTED event from the nRF8001
00506             if (aciEvt->params.device_started.hw_error) {
00507               delay(20); //Handle the HW error event correctly.
00508             } else {
00509               lib_aci_connect(0/* in seconds : 0 means forever */, ADVERTISING_INTERVAL);
00510 #ifdef NRF_8001_DEBUG
00511               Serial.println(F("Advertising started"));
00512 #endif
00513             }
00514             break;
00515         }
00516       }
00517       break; //ACI Device Started Event
00518 
00519       case ACI_EVT_CMD_RSP:
00520         //If an ACI command response event comes with an error -> stop
00521         if (ACI_STATUS_SUCCESS != aciEvt->params.cmd_rsp.cmd_status) {
00522           //ACI ReadDynamicData and ACI WriteDynamicData will have status codes of
00523           //TRANSACTION_CONTINUE and TRANSACTION_COMPLETE
00524           //all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command
00525 #ifdef NRF_8001_DEBUG
00526           Serial.print(F("ACI Command "));
00527           Serial.println(aciEvt->params.cmd_rsp.cmd_opcode, HEX);
00528           Serial.print(F("Evt Cmd respone: Status "));
00529           Serial.println(aciEvt->params.cmd_rsp.cmd_status, HEX);
00530 #endif
00531         } else {
00532           switch (aciEvt->params.cmd_rsp.cmd_opcode) {
00533             case ACI_CMD_GET_DEVICE_VERSION:
00534               break;
00535 
00536             case ACI_CMD_GET_DEVICE_ADDRESS: {
00537 #ifdef NRF_8001_DEBUG
00538               char address[18];
00539 
00540               sprintf(address, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
00541                 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[5],
00542                 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[4],
00543                 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[3],
00544                 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[2],
00545                 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[1],
00546                 aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[0]);
00547               Serial.print(F("Device address = "));
00548               Serial.println(address);
00549 
00550               Serial.print(F("Device address type = "));
00551               Serial.println(aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_type, DEC);
00552 #endif
00553               if (this->_eventListener) {
00554                 this->_eventListener->nRF8001AddressReceived(*this, aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own);
00555               }
00556               break;
00557             }
00558 
00559             case ACI_CMD_GET_BATTERY_LEVEL: {
00560               float batteryLevel = aciEvt->params.cmd_rsp.params.get_battery_level.battery_level * 0.00352;
00561 #ifdef NRF_8001_DEBUG
00562               Serial.print(F("Battery level = "));
00563               Serial.println(batteryLevel);
00564 #endif
00565               if (this->_eventListener) {
00566                 this->_eventListener->nRF8001BatteryLevelReceived(*this, batteryLevel);
00567               }
00568               break;
00569             }
00570 
00571             case ACI_CMD_GET_TEMPERATURE: {
00572               float temperature = aciEvt->params.cmd_rsp.params.get_temperature.temperature_value / 4.0;
00573 #ifdef NRF_8001_DEBUG
00574               Serial.print(F("Temperature = "));
00575               Serial.println(temperature);
00576 #endif
00577               if (this->_eventListener) {
00578                 this->_eventListener->nRF8001TemperatureReceived(*this, temperature);
00579               }
00580               break;
00581             }
00582           }
00583         }
00584         break;
00585 
00586       case ACI_EVT_CONNECTED:
00587 
00588 #ifdef NRF_8001_DEBUG
00589         char address[18];
00590         sprintf(address, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
00591           aciEvt->params.connected.dev_addr[5],
00592           aciEvt->params.connected.dev_addr[4],
00593           aciEvt->params.connected.dev_addr[3],
00594           aciEvt->params.connected.dev_addr[2],
00595           aciEvt->params.connected.dev_addr[1],
00596           aciEvt->params.connected.dev_addr[0]);
00597         Serial.print(F("Evt Connected "));
00598         Serial.println(address);
00599 #endif
00600         if (this->_eventListener) {
00601           this->_eventListener->nRF8001Connected(*this, aciEvt->params.connected.dev_addr);
00602         }
00603 
00604         this->_aciState.data_credit_available = this->_aciState.data_credit_total;
00605         break;
00606 
00607       case ACI_EVT_PIPE_STATUS:
00608 #ifdef NRF_8001_DEBUG
00609         Serial.println(F("Evt Pipe Status "));
00610 
00611         uint64_t openPipes;
00612         uint64_t closedPipes;
00613 
00614         memcpy(&openPipes, aciEvt->params.pipe_status.pipes_open_bitmap, sizeof(openPipes));
00615         memcpy(&closedPipes, aciEvt->params.pipe_status.pipes_closed_bitmap, sizeof(closedPipes));
00616 
00617         Serial.println((unsigned long)openPipes, HEX);
00618         Serial.println((unsigned long)closedPipes, HEX);
00619 #endif
00620 
00621         for (int i = 0; i < this->_numPipeInfo; i++) {
00622           struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
00623 
00624           if (pipeInfo->txPipe) {
00625             pipeInfo->txPipeOpen = lib_aci_is_pipe_available(&this->_aciState, pipeInfo->txPipe);
00626           }
00627 
00628           if (pipeInfo->txAckPipe) {
00629             pipeInfo->txAckPipeOpen = lib_aci_is_pipe_available(&this->_aciState, pipeInfo->txAckPipe);
00630           }
00631 
00632           bool subscribed = (pipeInfo->txPipeOpen || pipeInfo->txAckPipeOpen);
00633 
00634           if (pipeInfo->characteristic->subscribed() != subscribed) {
00635             if (this->_eventListener) {
00636               this->_eventListener->nRF8001CharacteristicSubscribedChanged(*this, *pipeInfo->characteristic, subscribed);
00637             }
00638           }
00639         }
00640         break;
00641 
00642       case ACI_EVT_TIMING:
00643         break;
00644 
00645       case ACI_EVT_DISCONNECTED:
00646 #ifdef NRF_8001_DEBUG
00647         Serial.println(F("Evt Disconnected/Advertising timed out"));
00648 #endif
00649         // all characteristics unsubscribed on disconnect
00650         for (int i = 0; i < this->_numPipeInfo; i++) {
00651           struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
00652 
00653           if (pipeInfo->characteristic->subscribed()) {
00654             if (this->_eventListener) {
00655               this->_eventListener->nRF8001CharacteristicSubscribedChanged(*this, *pipeInfo->characteristic, false);
00656             }
00657           }
00658         }
00659 
00660         if (this->_eventListener) {
00661           this->_eventListener->nRF8001Disconnected(*this);
00662         }
00663 
00664         lib_aci_connect(0/* in seconds  : 0 means forever */, ADVERTISING_INTERVAL);
00665 #ifdef NRF_8001_DEBUG
00666         Serial.println(F("Advertising started."));
00667 #endif
00668         break;
00669 
00670       case ACI_EVT_DATA_RECEIVED: {
00671         uint8_t dataLen = aciEvt->len - 2;
00672         uint8_t pipe = aciEvt->params.data_received.rx_data.pipe_number;
00673 #ifdef NRF_8001_DEBUG
00674         Serial.print(F("Data Received, pipe = "));
00675         Serial.println(aciEvt->params.data_received.rx_data.pipe_number, DEC);
00676 
00677         for (int i = 0; i < dataLen; i++) {
00678           if ((aciEvt->params.data_received.rx_data.aci_data[i] & 0xf0) == 00) {
00679             Serial.print("0");
00680           }
00681 
00682           Serial.print(aciEvt->params.data_received.rx_data.aci_data[i], HEX);
00683           Serial.print(F(" "));
00684         }
00685         Serial.println();
00686 #endif
00687 
00688         for (int i = 0; i < this->_numPipeInfo; i++) {
00689           struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
00690 
00691           if (pipeInfo->rxAckPipe == pipe || pipeInfo->rxPipe == pipe) {
00692             if (pipeInfo->rxAckPipe == pipe) {
00693               lib_aci_send_ack(&this->_aciState, pipeInfo->rxAckPipe);
00694             }
00695 
00696             if (this->_eventListener) {
00697               this->_eventListener->nRF8001CharacteristicValueChanged(*this, *pipeInfo->characteristic, aciEvt->params.data_received.rx_data.aci_data, dataLen);
00698             }
00699             break;
00700           }
00701         }
00702       }
00703         break;
00704 
00705       case ACI_EVT_DATA_CREDIT:
00706         this->_aciState.data_credit_available = this->_aciState.data_credit_available + aciEvt->params.data_credit.credit;
00707         break;
00708 
00709       case ACI_EVT_PIPE_ERROR:
00710         //See the appendix in the nRF8001 Product Specication for details on the error codes
00711 #ifdef NRF_8001_DEBUG
00712         Serial.print(F("ACI Evt Pipe Error: Pipe #:"));
00713         Serial.print(aciEvt->params.pipe_error.pipe_number, DEC);
00714         Serial.print(F("  Pipe Error Code: 0x"));
00715         Serial.println(aciEvt->params.pipe_error.error_code, HEX);
00716 #endif
00717 
00718         //Increment the credit available as the data packet was not sent.
00719         //The pipe error also represents the Attribute protocol Error Response sent from the peer and that should not be counted
00720         //for the credit.
00721         if (ACI_STATUS_ERROR_PEER_ATT_ERROR != aciEvt->params.pipe_error.error_code) {
00722           this->_aciState.data_credit_available++;
00723         }
00724         break;
00725 
00726       case ACI_EVT_HW_ERROR:
00727 #ifdef NRF_8001_DEBUG
00728         Serial.print(F("HW error: "));
00729         Serial.println(aciEvt->params.hw_error.line_num, DEC);
00730 
00731         for(uint8_t counter = 0; counter <= (aciEvt->len - 3); counter++) {
00732           Serial.write(aciEvt->params.hw_error.file_name[counter]); //uint8_t file_name[20];
00733         }
00734         Serial.println();
00735 #endif
00736         lib_aci_connect(0/* in seconds, 0 means forever */, ADVERTISING_INTERVAL);
00737 #ifdef NRF_8001_DEBUG
00738         Serial.println(F("Advertising started."));
00739 #endif
00740         break;
00741     }
00742   } else {
00743     //Serial.println(F("No ACI Events available"));
00744     // No event in the ACI Event queue and if there is no event in the ACI command queue the arduino can go to sleep
00745     // Arduino can go to sleep now
00746     // Wakeup from sleep from the RDYN line
00747   }
00748 }
00749 
00750 bool nRF8001::updateCharacteristicValue(BLECharacteristic& characteristic) {
00751   bool success = true;
00752 
00753   for (int i = 0; i < this->_numPipeInfo; i++) {
00754     struct pipeInfo* pipeInfo = &this->_pipeInfo[i];
00755 
00756     if (pipeInfo->characteristic == &characteristic) {
00757       if (pipeInfo->setPipe) {
00758         success &= lib_aci_set_local_data(&this->_aciState, pipeInfo->setPipe, (uint8_t*)characteristic.value(), characteristic.valueLength());
00759       }
00760 
00761       if (pipeInfo->txPipe && pipeInfo->txPipeOpen) {
00762         if (this->canNotifyCharacteristic(characteristic)) {
00763           this->_aciState.data_credit_available--;
00764           success &= lib_aci_send_data(pipeInfo->txPipe, (uint8_t*)characteristic.value(), characteristic.valueLength());
00765         } else {
00766           success = false;
00767         }
00768       }
00769 
00770       if (pipeInfo->txAckPipe && pipeInfo->txAckPipeOpen) {
00771         if (this->canIndicateCharacteristic(characteristic)) {
00772           this->_aciState.data_credit_available--;
00773           success &= lib_aci_send_data(pipeInfo->txAckPipe, (uint8_t*)characteristic.value(), characteristic.valueLength());
00774         } else {
00775           success = false;
00776         }
00777       }
00778 
00779       break;
00780     }
00781   }
00782 
00783   return success;
00784 }
00785 
00786 bool nRF8001::canNotifyCharacteristic(BLECharacteristic& characteristic) {
00787   return (lib_aci_get_nb_available_credits(&this->_aciState) > 0);
00788 }
00789 
00790 bool nRF8001::canIndicateCharacteristic(BLECharacteristic& characteristic) {
00791   return (lib_aci_get_nb_available_credits(&this->_aciState) > 0);
00792 }
00793 
00794 void nRF8001::disconnect() {
00795   lib_aci_disconnect(&this->_aciState, ACI_REASON_TERMINATE);
00796 }
00797 void nRF8001::requestAddress() {
00798   lib_aci_get_address();
00799 }
00800 
00801 void nRF8001::requestTemperature() {
00802   lib_aci_get_temperature();
00803 }
00804 
00805 void nRF8001::requestBatteryLevel() {
00806   lib_aci_get_battery_level();
00807 }
00808 
00809 void nRF8001::waitForSetupMode()
00810 {
00811   bool setupMode = false;
00812 
00813   while (!setupMode) {
00814     if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
00815       aci_evt_t* aciEvt = &this->_aciData.evt;
00816 
00817       switch(aciEvt->evt_opcode) {
00818         case ACI_EVT_DEVICE_STARTED: {
00819           switch(aciEvt->params.device_started.device_mode) {
00820             case ACI_DEVICE_SETUP:
00821               /**
00822               When the device is in the setup mode
00823               */
00824 #ifdef NRF_8001_DEBUG
00825               Serial.println(F("Evt Device Started: Setup"));
00826 #endif
00827               setupMode = true;
00828               break;
00829           }
00830         }
00831       }
00832     } else {
00833       delay(1);
00834     }
00835   }
00836 }
00837 
00838 void nRF8001::sendSetupMessage(hal_aci_data_t* data)
00839 {
00840   this->_crcSeed = crc_16_ccitt(this->_crcSeed, data->buffer, data->buffer[0] + 1);
00841 
00842 #ifdef NRF_8001_DEBUG
00843   for (int j = 0; j < (data->buffer[0] + 1); j++) {
00844     if ((data->buffer[j] & 0xf0) == 00) {
00845       Serial.print("0");
00846     }
00847 
00848     Serial.print(data->buffer[j], HEX);
00849     Serial.print(" ");
00850   }
00851   Serial.println();
00852 #endif
00853 
00854   hal_aci_tl_send(data);
00855 
00856   bool setupMsgSent = false;
00857 
00858   while (!setupMsgSent) {
00859     if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
00860       aci_evt_t* aciEvt = &this->_aciData.evt;
00861 
00862       switch(aciEvt->evt_opcode) {
00863         case ACI_EVT_CMD_RSP: {
00864           switch(aciEvt->params.cmd_rsp.cmd_status) {
00865             case ACI_STATUS_TRANSACTION_CONTINUE:
00866 #ifdef NRF_8001_DEBUG
00867               Serial.println(F("Evt Cmd Rsp: Transaction Continue"));
00868 #endif
00869               setupMsgSent = true;
00870               break;
00871           }
00872         }
00873       }
00874     } else {
00875       delay(1);
00876     }
00877   }
00878 }
00879 
00880 void nRF8001::sendCrc()
00881 {
00882   hal_aci_data_t data;
00883   data.status_byte = 0;
00884 
00885   data.buffer[0]  = 3 + 3;
00886   data.buffer[1]  = ACI_CMD_SETUP;
00887   data.buffer[2]  = 0xf0;
00888   data.buffer[3]  = 0x00;
00889 
00890   data.buffer[4] = 0x03;
00891 
00892   this->_crcSeed = crc_16_ccitt(this->_crcSeed, data.buffer, data.buffer[0] - 1);
00893 
00894   data.buffer[5] = (this->_crcSeed >> 8) & 0xff;
00895   data.buffer[6] = this->_crcSeed & 0xff;
00896 
00897 #ifdef NRF_8001_DEBUG
00898   for (int j = 0; j < (data.buffer[0] + 1); j++) {
00899     if ((data.buffer[j] & 0xf0) == 00) {
00900       Serial.print("0");
00901     }
00902 
00903     Serial.print(data.buffer[j], HEX);
00904     Serial.print(" ");
00905   }
00906   Serial.println();
00907 #endif
00908 
00909   hal_aci_tl_send(&data);
00910 
00911   bool setupMsgSent = false;
00912 
00913   while (!setupMsgSent) {
00914     if (lib_aci_event_get(&this->_aciState, &this->_aciData)) {
00915       aci_evt_t* aciEvt = &this->_aciData.evt;
00916 
00917       switch(aciEvt->evt_opcode) {
00918         case ACI_EVT_CMD_RSP: {
00919           switch(aciEvt->params.cmd_rsp.cmd_status) {
00920             case ACI_STATUS_TRANSACTION_COMPLETE:
00921 #ifdef NRF_8001_DEBUG
00922               Serial.println(F("Evt Cmd Rsp: Transaction Complete"));
00923 #endif
00924               setupMsgSent = true;
00925               break;
00926           }
00927         }
00928       }
00929     } else {
00930       delay(1);
00931     }
00932   }
00933 }