examples: Remove heap allocation from C++ examples

Cleanup of UPM C++ examples.  Switched from heap allocation to
stack allocation when possible.  This simplifies the samples since it
removes the need for explicit memory management.  A script was used to
identify and replace pointer use.  To simplify the replace script, I
re-formatted the C++ examples using the UPM .clang-format file.
Unfortuantely this changes the look of the UPM C++ examples to a large
degree.  However, examples will now have a standard look/feel and
uniform formatting.

    * Ran clang-format w/provided UPM .clang-format file
    * Removed new's/delete's whenever possible (left those in interface
      examples)
    * Added IIO sensor library implementation of callback void* arg
    * Converted all sleeps to upm defined delays (added header when
      necessary)
    * Scrubbed CXX example includes

Signed-off-by: Noel Eck <noel.eck@intel.com>
This commit is contained in:
Noel Eck
2017-08-30 15:00:29 -07:00
committed by Mihai Tudor Panu
parent bd6e4ec786
commit 5cefe7f5f3
290 changed files with 7976 additions and 8520 deletions

View File

@ -22,27 +22,35 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include "nrf8001.hpp"
#include "nrf8001-helloworld.hpp"
#include <lib_aci.h>
#include <aci_setup.h>
#include <signal.h>
#include <assert.h>
#include <iostream>
#include <lib_aci.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "aci_cmds.h"
#include "aci_evts.h"
#include "hal_aci_tl.h"
#include "nrf8001-helloworld.hpp"
#include "nrf8001.hpp"
#include "uart_over_ble.h"
#include "upm_utilities.h"
/*
* You can use the nRF UART app in the Apple iOS app store and Google Play for Android 4.3 for Samsung Galaxy S4
* You can use the nRF UART app in the Apple iOS app store and Google Play for
* Android 4.3 for Samsung Galaxy S4
* with this helloworld application
*/
#ifdef SERVICES_PIPE_TYPE_MAPPING_CONTENT
static services_pipe_type_mapping_t
services_pipe_type_mapping[NUMBER_OF_PIPES] = SERVICES_PIPE_TYPE_MAPPING_CONTENT;
static services_pipe_type_mapping_t services_pipe_type_mapping[NUMBER_OF_PIPES] =
SERVICES_PIPE_TYPE_MAPPING_CONTENT;
#else
#define NUMBER_OF_PIPES 0
static services_pipe_type_mapping_t * services_pipe_type_mapping = NULL;
#define NUMBER_OF_PIPES 0
static services_pipe_type_mapping_t* services_pipe_type_mapping = NULL;
#endif
/**
@ -54,7 +62,7 @@ static hal_aci_data_t setup_msgs[NB_SETUP_MESSAGES] = SETUP_MESSAGES_CONTENT;
* aci_struct that will contain
* total initial credits
* current credit
* current state of the aci (setup/standby/active/sleep)
* current state of the aci (setup/standby/active/upm_delay)
* open remote pipe pending
* close remote pipe pending
* Current pipe available bitmap
@ -68,19 +76,19 @@ static struct aci_state_t aci_state;
/**
* Temporary buffers for sending ACI commands
*/
static hal_aci_evt_t aci_data;
static hal_aci_evt_t aci_data;
/*
Timing change state variable
*/
static bool timing_change_done = false;
static bool timing_change_done = false;
/*
Used to test the UART TX characteristic notification
*/
static uart_over_ble_t uart_over_ble;
static uint8_t uart_buffer[20];
static uint8_t uart_buffer_len = 0;
static uint8_t uart_buffer[20];
static uint8_t uart_buffer_len = 0;
void
sig_handler(int signo)
@ -92,31 +100,34 @@ sig_handler(int signo)
}
void
init_aci_setup () {
init_aci_setup()
{
/**
* Point ACI data structures to the the setup data that the nRFgo studio generated for the nRF8001
*/
* Point ACI data structures to the the setup data that the nRFgo studio
* generated for the nRF8001
*/
// abort if this is NULL
assert(services_pipe_type_mapping != NULL);
aci_state.aci_setup_info.services_pipe_type_mapping =
&services_pipe_type_mapping[0];
aci_state.aci_setup_info.services_pipe_type_mapping = &services_pipe_type_mapping[0];
aci_state.aci_setup_info.number_of_pipes = NUMBER_OF_PIPES;
aci_state.aci_setup_info.setup_msgs = setup_msgs;
aci_state.aci_setup_info.num_setup_msgs = NB_SETUP_MESSAGES;
aci_state.aci_setup_info.number_of_pipes = NUMBER_OF_PIPES;
aci_state.aci_setup_info.setup_msgs = setup_msgs;
aci_state.aci_setup_info.num_setup_msgs = NB_SETUP_MESSAGES;
}
void
uart_over_ble_init (void) {
uart_over_ble_init(void)
{
uart_over_ble.uart_rts_local = true;
}
bool
uart_tx (uint8_t *buffer, uint8_t buffer_len) {
uart_tx(uint8_t* buffer, uint8_t buffer_len)
{
bool status = false;
if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) &&
if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) &&
(aci_state.data_credit_available >= 1)) {
status = lib_aci_send_data(PIPE_UART_OVER_BTLE_UART_TX_TX, buffer, buffer_len);
if (status) {
@ -128,67 +139,68 @@ uart_tx (uint8_t *buffer, uint8_t buffer_len) {
}
bool
uart_process_control_point_rx(uint8_t *byte, uint8_t length) {
uart_process_control_point_rx(uint8_t* byte, uint8_t length)
{
bool status = false;
aci_ll_conn_params_t *conn_params;
aci_ll_conn_params_t* conn_params;
if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_TX) ) {
if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_TX)) {
switch (*byte) {
/*
Queues a ACI Disconnect to the nRF8001 when this packet is received.
May cause some of the UART packets being sent to be dropped
*/
Queues a ACI Disconnect to the nRF8001 when this packet is received.
May cause some of the UART packets being sent to be dropped
*/
case UART_OVER_BLE_DISCONNECT:
/*
Parameters:
None
*/
Parameters:
None
*/
lib_aci_disconnect(&aci_state, ACI_REASON_TERMINATE);
status = true;
break;
/*
Queues an ACI Change Timing to the nRF8001
*/
Queues an ACI Change Timing to the nRF8001
*/
case UART_OVER_BLE_LINK_TIMING_REQ:
/*
Parameters:
Connection interval min: 2 bytes
Connection interval max: 2 bytes
Slave latency: 2 bytes
Timeout: 2 bytes
Same format as Peripheral Preferred Connection Parameters (See nRFgo studio -> nRF8001 Configuration -> GAP Settings
Refer to the ACI Change Timing Request in the nRF8001 Product Specifications
*/
conn_params = (aci_ll_conn_params_t *)(byte+1);
lib_aci_change_timing( conn_params->min_conn_interval,
conn_params->max_conn_interval,
conn_params->slave_latency,
conn_params->timeout_mult);
Parameters:
Connection interval min: 2 bytes
Connection interval max: 2 bytes
Slave latency: 2 bytes
Timeout: 2 bytes
Same format as Peripheral Preferred Connection Parameters (See nRFgo studio ->
nRF8001 Configuration -> GAP Settings
Refer to the ACI Change Timing Request in the nRF8001 Product Specifications
*/
conn_params = (aci_ll_conn_params_t*) (byte + 1);
lib_aci_change_timing(conn_params->min_conn_interval,
conn_params->max_conn_interval,
conn_params->slave_latency,
conn_params->timeout_mult);
status = true;
break;
/*
Clears the RTS of the UART over BLE
*/
Clears the RTS of the UART over BLE
*/
case UART_OVER_BLE_TRANSMIT_STOP:
/*
Parameters:
None
*/
Parameters:
None
*/
uart_over_ble.uart_rts_local = false;
status = true;
break;
/*
Set the RTS of the UART over BLE
*/
Set the RTS of the UART over BLE
*/
case UART_OVER_BLE_TRANSMIT_OK:
/*
Parameters:
None
*/
Parameters:
None
*/
uart_over_ble.uart_rts_local = true;
status = true;
break;
@ -199,109 +211,132 @@ uart_process_control_point_rx(uint8_t *byte, uint8_t length) {
}
int
main(int argc, char **argv)
main(int argc, char** argv)
{
//! [Interesting]
init_aci_setup ();
init_local_interfaces (&aci_state, 10, 8, 4);
init_aci_setup();
init_local_interfaces(&aci_state, 10, 8, 4);
while (1) {
static bool setup_required = false;
// We enter the if statement only when there is a ACI event available to be processed
// 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_t* aci_evt;
aci_evt = &aci_data.evt;
switch(aci_evt->evt_opcode) {
switch (aci_evt->evt_opcode) {
/**
As soon as you reset the nRF8001 you will get an ACI Device Started Event
*/
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) {
switch (aci_evt->params.device_started.device_mode) {
case ACI_DEVICE_SETUP:
/**
When the device is in the setup mode
*/
printf ("Evt Device Started: Setup \n");
When the device is in the setup mode
*/
printf("Evt Device Started: Setup \n");
setup_required = true;
break;
case ACI_DEVICE_STANDBY:
printf ("Evt Device Started: Standby \n");
// 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
printf("Evt Device Started: Standby \n");
// 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) {
usleep (20000); //Handle the HW error event correctly.
upm_delay_us(20000); // Handle the HW error
// event correctly.
} else {
lib_aci_connect(0/* in seconds : 0 means forever */, 0x0050 /* advertising interval 50ms*/);
printf ("Advertising started \n");
lib_aci_connect(0 /* in seconds : 0 means forever */,
0x0050 /* advertising interval 50ms*/);
printf("Advertising started \n");
}
break;
default:
break;
}
}
break; // ACI Device Started Event
} break; // ACI Device Started Event
case ACI_EVT_CMD_RSP:
//If an ACI command response event comes with an error -> stop
// 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
printf ("ACI_EVT_CMD_RSP \n");
// 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
printf("ACI_EVT_CMD_RSP \n");
}
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));
// 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:
printf ("ACI_EVT_CONNECTED");
uart_over_ble_init ();
printf("ACI_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
*/
Get the device version of the nRF8001 and store it in the Hardware Revision
String
*/
lib_aci_device_version();
break;
case ACI_EVT_PIPE_STATUS:
printf ("ACI_EVT_PIPE_STATUS \n");
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
printf("ACI_EVT_PIPE_STATUS \n");
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;
char hello[]="Hello World, works";
uart_tx((uint8_t *)&hello[0], strlen(hello));
char hello[] = "Hello World, works";
uart_tx((uint8_t*) &hello[0], strlen(hello));
}
break;
case ACI_EVT_TIMING:
printf ("Evt link connection interval changed \n");
printf("Evt link connection interval changed \n");
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);
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:
printf ("ACI_EVT_DISCONNECTED \n");
lib_aci_connect(0/* in seconds : 0 means forever */, 0x0050 /* advertising interval 50ms*/);
printf ("Advertising started \n");
printf("ACI_EVT_DISCONNECTED \n");
lib_aci_connect(0 /* in seconds : 0 means forever */,
0x0050 /* advertising interval 50ms*/);
printf("Advertising started \n");
break;
case ACI_EVT_DATA_RECEIVED:
if (PIPE_UART_OVER_BTLE_UART_RX_RX == aci_evt->params.data_received.rx_data.pipe_number) {
for(int i=0; i<aci_evt->len - 2; i++) {
uart_buffer[i] = aci_evt->params.data_received.rx_data.aci_data[i];
if (PIPE_UART_OVER_BTLE_UART_RX_RX ==
aci_evt->params.data_received.rx_data.pipe_number) {
for (int i = 0; i < aci_evt->len - 2; i++) {
uart_buffer[i] = aci_evt->params.data_received.rx_data.aci_data[i];
}
uart_buffer_len = aci_evt->len - 2;
@ -309,53 +344,60 @@ main(int argc, char **argv)
}
}
if (PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX == aci_evt->params.data_received.rx_data.pipe_number) {
//Subtract for Opcode and Pipe number
uart_process_control_point_rx(&aci_evt->params.data_received.rx_data.aci_data[0], aci_evt->len - 2);
if (PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX ==
aci_evt->params.data_received.rx_data.pipe_number) {
// Subtract for Opcode and Pipe number
uart_process_control_point_rx(
&aci_evt->params.data_received.rx_data.aci_data[0], aci_evt->len - 2);
}
printf ("Incomming data - %s\n", uart_buffer);
printf("Incomming data - %s\n", uart_buffer);
break;
case ACI_EVT_DATA_CREDIT:
printf ("ACI_EVT_DATA_CREDIT \n");
aci_state.data_credit_available = aci_state.data_credit_available + aci_evt->params.data_credit.credit;
printf("ACI_EVT_DATA_CREDIT \n");
aci_state.data_credit_available =
aci_state.data_credit_available + aci_evt->params.data_credit.credit;
break;
case ACI_EVT_PIPE_ERROR:
printf ("ACI_EVT_PIPE_ERROR \n");
//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.
printf("ACI_EVT_PIPE_ERROR \n");
// 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:
printf ("ACI_EVT_HW_ERROR \n");
lib_aci_connect(0/* in seconds, 0 means forever */, 0x0050 /* advertising interval 50ms*/);
printf ("Advertising started \n");
break;
printf("ACI_EVT_HW_ERROR \n");
lib_aci_connect(0 /* in seconds, 0 means forever */,
0x0050 /* advertising interval 50ms*/);
printf("Advertising started \n");
break;
default:
break;
break;
}
}
/* 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) {
/* 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;
}
}
usleep (100);
upm_delay_us(100);
}
close_local_interfaces (&aci_state);
close_local_interfaces(&aci_state);
//! [Interesting]