void Adafruit_BLE_UART::pollACI() { // We enter the if statement only when there is a ACI event available to be processed if (lib_aci_event_get(&aci_state, &aci_data)) { aci_evt_t * aci_evt; aci_evt = &aci_data.evt; switch(aci_evt->evt_opcode) { /* As soon as you reset the nRF8001 you will get an ACI Device Started Event */ case ACI_EVT_DEVICE_STARTED: { aci_state.data_credit_total = aci_evt->params.device_started.credit_available; switch(aci_evt->params.device_started.device_mode) { case ACI_DEVICE_SETUP: /* Device is in setup mode! */ if (ACI_STATUS_TRANSACTION_COMPLETE != do_aci_setup(&aci_state)) { if (debugMode) { Serial.println(F("Error in ACI Setup")); } } break; case ACI_DEVICE_STANDBY: /* Start advertising ... first value is advertising time in seconds, the */ /* second value is the advertising interval in 0.625ms units */ if (device_name[0] != 0x00) { /* Update the device name */ lib_aci_set_local_data(&aci_state, PIPE_GAP_DEVICE_NAME_SET , (uint8_t *)&device_name, strlen(device_name)); } lib_aci_connect(adv_timeout, adv_interval); defaultACICallback(ACI_EVT_DEVICE_STARTED); if (aci_event) aci_event(ACI_EVT_DEVICE_STARTED); } } break; case ACI_EVT_CMD_RSP: /* If an ACI command response event comes with an error -> stop */ if (ACI_STATUS_SUCCESS != aci_evt->params.cmd_rsp.cmd_status) { // ACI ReadDynamicData and ACI WriteDynamicData will have status codes of // TRANSACTION_CONTINUE and TRANSACTION_COMPLETE // all other ACI commands will have status code of ACI_STATUS_SUCCESS for a successful command if (debugMode) { Serial.print(F("ACI Command ")); Serial.println(aci_evt->params.cmd_rsp.cmd_opcode, HEX); Serial.println(F("Evt Cmd respone: Error. Arduino is in an while(1); loop")); } while (1); } if (ACI_CMD_GET_DEVICE_VERSION == aci_evt->params.cmd_rsp.cmd_opcode) { // Store the version and configuration information of the nRF8001 in the Hardware Revision String Characteristic lib_aci_set_local_data(&aci_state, PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET, (uint8_t *)&(aci_evt->params.cmd_rsp.params.get_device_version), sizeof(aci_evt_cmd_rsp_params_get_device_version_t)); } break; case ACI_EVT_CONNECTED: aci_state.data_credit_available = aci_state.data_credit_total; /* Get the device version of the nRF8001 and store it in the Hardware Revision String */ lib_aci_device_version(); defaultACICallback(ACI_EVT_CONNECTED); if (aci_event) aci_event(ACI_EVT_CONNECTED); case ACI_EVT_PIPE_STATUS: if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) && (false == timing_change_done)) { lib_aci_change_timing_GAP_PPCP(); // change the timing on the link as specified in the nRFgo studio -> nRF8001 conf. -> GAP. // Used to increase or decrease bandwidth timing_change_done = true; } break; case ACI_EVT_TIMING: /* Link connection interval changed */ break; case ACI_EVT_DISCONNECTED: /* Restart advertising ... first value is advertising time in seconds, the */ /* second value is the advertising interval in 0.625ms units */ defaultACICallback(ACI_EVT_DISCONNECTED); if (aci_event) aci_event(ACI_EVT_DISCONNECTED); lib_aci_connect(adv_timeout, adv_interval); defaultACICallback(ACI_EVT_DEVICE_STARTED); if (aci_event) aci_event(ACI_EVT_DEVICE_STARTED); break; case ACI_EVT_DATA_RECEIVED: defaultRX(aci_evt->params.data_received.rx_data.aci_data, aci_evt->len - 2); if (rx_event) rx_event(aci_evt->params.data_received.rx_data.aci_data, aci_evt->len - 2); break; case ACI_EVT_DATA_CREDIT: aci_state.data_credit_available = aci_state.data_credit_available + aci_evt->params.data_credit.credit; break; case ACI_EVT_PIPE_ERROR: /* See the appendix in the nRF8001 Product Specication for details on the error codes */ if (debugMode) { Serial.print(F("ACI Evt Pipe Error: Pipe #:")); Serial.print(aci_evt->params.pipe_error.pipe_number, DEC); Serial.print(F(" Pipe Error Code: 0x")); Serial.println(aci_evt->params.pipe_error.error_code, HEX); } /* Increment the credit available as the data packet was not sent */ aci_state.data_credit_available++; break; } } else { // Serial.println(F("No ACI Events available")); // No event in the ACI Event queue and if there is no event in the ACI command queue the arduino can go to sleep // Arduino can go to sleep now // Wakeup from sleep from the RDYN line } }
void Adafruit_BLE_UART::pollACI() { static bool setup_required = false; // We enter the if statement only when there is a ACI event available to be processed if (lib_aci_event_get(&aci_state, &aci_data)) { aci_evt_t * aci_evt; aci_evt = &aci_data.evt; switch(aci_evt->evt_opcode) { /** As soon as you reset the nRF8001 you will get an ACI Device Started Event */ case ACI_EVT_DEVICE_STARTED: { aci_state.data_credit_total = aci_evt->params.device_started.credit_available; switch(aci_evt->params.device_started.device_mode) { case ACI_DEVICE_SETUP: /** When the device is in the setup mode */ Serial.println(F("Evt Device Started: Setup")); setup_required = true; break; case ACI_DEVICE_STANDBY: Serial.println(F("Evt Device Started: Standby")); //Looking for an iPhone by sending radio advertisements //When an iPhone connects to us we will get an ACI_EVT_CONNECTED event from the nRF8001 if (aci_evt->params.device_started.hw_error) { delay(20); //Handle the HW error event correctly. if (debugMode) { Serial.println(F("Error in ACI Setup")); } } else { lib_aci_connect(0/* in seconds : 0 means forever */, 0x0050 /* advertising interval 50ms*/); defaultACICallback(ACI_EVT_DEVICE_STARTED); Serial.println(F("Advertising started : Tap Connect on the nRF UART app or client application")); } break; } } break; //ACI Device Started Event case ACI_EVT_CMD_RSP: //If an ACI command response event comes with an error -> stop if (ACI_STATUS_SUCCESS != aci_evt->params.cmd_rsp.cmd_status) { //ACI ReadDynamicData and ACI WriteDynamicData will have status codes of //TRANSACTION_CONTINUE and TRANSACTION_COMPLETE //all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command Serial.print(F("ACI Command ")); Serial.println(aci_evt->params.cmd_rsp.cmd_opcode, HEX); Serial.print(F("Evt Cmd respone: Status ")); Serial.println(aci_evt->params.cmd_rsp.cmd_status, HEX); } if (ACI_CMD_GET_DEVICE_VERSION == aci_evt->params.cmd_rsp.cmd_opcode) { //Store the version and configuration information of the nRF8001 in the Hardware Revision String Characteristic lib_aci_set_local_data(&aci_state, PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET, (uint8_t *)&(aci_evt->params.cmd_rsp.params.get_device_version), sizeof(aci_evt_cmd_rsp_params_get_device_version_t)); } break; case ACI_EVT_CONNECTED: Serial.println(F("Evt Connected")); uart_over_ble_init(); timing_change_done = false; aci_state.data_credit_available = aci_state.data_credit_total; /* Get the device version of the nRF8001 and store it in the Hardware Revision String */ lib_aci_device_version(); defaultACICallback(ACI_EVT_CONNECTED); break; case ACI_EVT_PIPE_STATUS: Serial.println(F("Evt Pipe Status")); if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) && (false == timing_change_done)) { lib_aci_change_timing_GAP_PPCP(); // change the timing on the link as specified in the nRFgo studio -> nRF8001 conf. -> GAP. // Used to increase or decrease bandwidth timing_change_done = true; } break; case ACI_EVT_TIMING: Serial.println(F("Evt link connection interval changed")); lib_aci_set_local_data(&aci_state, PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET, (uint8_t *)&(aci_evt->params.timing.conn_rf_interval), /* Byte aligned */ PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET_MAX_SIZE); break; case ACI_EVT_DISCONNECTED: defaultACICallback(ACI_EVT_DISCONNECTED); Serial.println(F("Evt Disconnected/Advertising timed out")); lib_aci_connect(0/* in seconds : 0 means forever */, 0x0050 /* advertising interval 50ms*/); defaultACICallback(ACI_EVT_DEVICE_STARTED); Serial.println(F("Advertising started. Tap Connect on the nRF UART app")); break; case ACI_EVT_DATA_RECEIVED: Serial.print(F("Pipe Number: ")); Serial.println(aci_evt->params.data_received.rx_data.pipe_number, DEC); defaultRX(aci_evt->params.data_received.rx_data.aci_data, aci_evt->len - 2); if (rx_event) { rx_event(aci_evt->params.data_received.rx_data.aci_data, aci_evt->len - 2); } if (PIPE_UART_OVER_BTLE_UART_RX_RX == aci_evt->params.data_received.rx_data.pipe_number) { Serial.print(F(" Data(Hex) : ")); for(int i=0; i<aci_evt->len - 2; i++) { Serial.print((char)aci_evt->params.data_received.rx_data.aci_data[i]); uart_buffer[i] = aci_evt->params.data_received.rx_data.aci_data[i]; Serial.print(F(" ")); } uart_buffer_len = aci_evt->len - 2; Serial.println(F("")); if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX)) { /*Do this to test the loopback otherwise comment it out*/ /* if (!uart_tx(&uart_buffer[0], aci_evt->len - 2)) { Serial.println(F("UART loopback failed")); } else { Serial.println(F("UART loopback OK")); } */ } } if (PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX == aci_evt->params.data_received.rx_data.pipe_number) { uart_process_control_point_rx(&aci_evt->params.data_received.rx_data.aci_data[0], aci_evt->len - 2); //Subtract for Opcode and Pipe number } break; case ACI_EVT_DATA_CREDIT: aci_state.data_credit_available = aci_state.data_credit_available + aci_evt->params.data_credit.credit; break; case ACI_EVT_PIPE_ERROR: //See the appendix in the nRF8001 Product Specication for details on the error codes if ( debugMode ) { Serial.print(F("ACI Evt Pipe Error: Pipe #:")); Serial.print(aci_evt->params.pipe_error.pipe_number, DEC); Serial.print(F(" Pipe Error Code: 0x")); Serial.println(aci_evt->params.pipe_error.error_code, HEX); } //Increment the credit available as the data packet was not sent. //The pipe error also represents the Attribute protocol Error Response sent from the peer and that should not be counted //for the credit. if (ACI_STATUS_ERROR_PEER_ATT_ERROR != aci_evt->params.pipe_error.error_code) { aci_state.data_credit_available++; } break; case ACI_EVT_HW_ERROR: Serial.print(F("HW error: ")); Serial.println(aci_evt->params.hw_error.line_num, DEC); for(uint8_t counter = 0; counter <= (aci_evt->len - 3); counter++) { Serial.write(aci_evt->params.hw_error.file_name[counter]); //uint8_t file_name[20]; } Serial.println(); lib_aci_connect(0/* in seconds, 0 means forever */, 0x0050 /* advertising interval 50ms*/); Serial.println(F("Advertising started. Tap Connect on the nRF UART app")); break; } } else { if ( debugMode ) { //Serial.println(F("No ACI Events available")); } // No event in the ACI Event queue and if there is no event in the ACI command queue the arduino can go to sleep // Arduino can go to sleep now // Wakeup from sleep from the RDYN line } /* setup_required is set to true when the device starts up and enters setup mode. * It indicates that do_aci_setup() should be called. The flag should be cleared if * do_aci_setup() returns ACI_STATUS_TRANSACTION_COMPLETE. */ if(setup_required) { if (SETUP_SUCCESS == do_aci_setup(&aci_state)) { setup_required = false; } } }