Queue buffer and sd_ble_gatts_hvx() - is my approach correct?

Hi guys,

I have developed an app to read data from some sensors and notify the central with a frequency of 100Hz. It seems to work but I would like to share my approach and let me know of any improvements

I have two application timers. The first one expires every 200us and sample some pressure sensors and the second expires every every 10ms. The 10ms timer calls the read_sensors(), where I sample the IMU (IMU_read()), increment a packet counter (packet_increment()), buffer the sensors data (my_sensors_buffer()) and attempt to transmit (data_tx())

void read_sensors(void *p_context) {

  ret_code_t err_code;
  UNUSED_PARAMETER(p_context);

  // Read the IMU
  IMU_read(&sampling);

  // Increment the packet counter
  packet_increment(&sampling,false);

  logger(&sampling);

  // Buffer that payload
  my_sensors_buffer(&sampling);

  // if the buffer is not empty Tx data
  if (!nrf_queue_is_empty(&m_sensor_data_queue)) {
    data_tx(&sampling);
  }
}

I buffer the data using the queue library

void my_sensors_buffer(struct s_sampling *sampling) {

  ret_code_t err_code;
  uint16_t queue_available_space;

  int8_t *payload = (int8_t *)sampling;

  // Buffer the payload (32bytes)
  for (uint16_t i = 0; i < sampling->size_of_payload; i++) {
    err_code = nrf_queue_push(&m_sensor_data_queue, payload++);
    APP_ERROR_CHECK(err_code);
  }
}

When I call the data_tx() I try to transmit all the queued data while (err_code == NRF_SUCCESS)

The ble_cus_custom_value_update() gives a call to sd_ble_gatts_hvx()

void data_tx(struct s_sampling *sampling) {
  ret_code_t err_code;
  uint16_t queue_available_space;

  err_code = NRF_SUCCESS;
  while (err_code == NRF_SUCCESS) {

    if (!sampling->busy) {
      err_code = nrf_queue_read(&m_sensor_data_queue, sampling->tx_buffer, sampling->size_of_payload); // QUEUE_SIZE <= queue_utilization_get(p_queue)
      APP_ERROR_CHECK(err_code);
    }

    err_code = ble_cus_custom_value_update(&m_cus, sampling);
    if (err_code != NRF_ERROR_INVALID_STATE && err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING && err_code != NRF_ERROR_RESOURCES && err_code != NRF_ERROR_BUSY) { //
      APP_ERROR_CHECK(err_code);
    }

    if (err_code == NRF_ERROR_RESOURCES) {
      NRF_LOG_INFO("Error: %d ", err_code)
      sampling->busy = true;
      break;
    }
    
    sampling->busy = false;

    if (nrf_queue_is_empty(&m_sensor_data_queue)) {
      NRF_LOG_INFO("Queue is empty");
      begin = app_timer_cnt_get(); // na - get the current ticks after just before notification (32bit long number)
      NRF_LOG_INFO("Current ticks(empty queue) %d", begin)
      break;
    }
  }
}

In case of NRF_ERROR_RESOURCES I wait for the BLE_GATTS_EVT_HVN_TX_COMPLETE event and call again the data_tx() 

case BLE_GATTS_EVT_HVN_TX_COMPLETE:
    packet_count = p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count;
    NRF_LOG_INFO("BLE_GATTS_EVT_HVN_TX_COMPLETE");
    NRF_LOG_INFO("Packet count: %d", packet_count);
    on_tx_complete(&sampling);
    break;

static void on_tx_complete(struct s_sampling *sampling) {
  if (sampling->busy) { // if busy is true, there are still data in the buffer
    data_tx(sampling);
  }
}

This is the block diagram. A bit complicated :/

Related