This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Trying to get data from pressure sensor via SPIS

Hello.

I'm trying to get data from a pressure sensor.

But it seems that BLE device is not properly got data from the sensor.

Here is a data sheet of the sensor. (Please see page 15 how I made a custom board for the sensor and how I wired.)

I'm developing with my custom boards.(Boss of nRF52832 and the sensor.)

My code is below.

#include <stdbool.h>
#include <stdint.h>
#include "nordic_common.h"
#include "bsp.h"
#include "nrf_soc.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "ble_advdata.h"
#include "app_timer.h"
#include "nrf_pwr_mgmt.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "nrf_drv_spi.h"
#include "ble_advertising.h"
#include "ble_gap.h"

#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"

#include "nrf_spi_mngr.h"

#include "sdk_config.h"
#include "nrf_drv_spis.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>

#if defined (LEGACY_DEFINE)

#undef NRFX_DEFINE
#define NRFX_DEFINE LEGACY_DEFINE

#endif 


#define APP_BLE_CONN_CFG_TAG            1                                  /**< A tag identifying the SoftDevice BLE configuration. */
#define APP_BLE_OBSERVER_PRIO           3                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
//#define APP_BLE_OBSERVER_PRIO           1                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */

//#define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
//#define CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_1_25_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
#define CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(12500, UNIT_1_25_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */

#define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */

#define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */

#define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
#define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */

//#define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_COMPANY_IDENTIFIER          0x004C                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
#define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
#define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                        0x45, 0x56, 0x67, 0x78, \
                                        0x89, 0x9a, 0xab, 0xbc, \
                                        0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */
            
#define APP_SIGNAL_OUT                  0xc3                              /**< Proprietary SIGNAL OUT for Beacon. */

#define DEAD_BEEF                       0xDEADBEEF                         /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
#define MAJ_VAL_OFFSET_IN_BEACON_INFO   18                                 /**< Position of the MSB of the Major Value in m_beacon_info array. */
#define UICR_ADDRESS                    0x10001080                         /**< Address of the UICR register used by this example. The major and minor versions to be encoded into the advertising data will be picked up from this location. */
#endif

static ble_gap_adv_params_t m_adv_params;                                  /**< Parameters to be passed to the stack when starting advertising. */
static uint8_t              m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
static uint8_t              m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded advertising set. */

//NRF_BLE_GATT_DEF(m_gatt);                                                       /**< GATT module instance. */

#define UPDATE_MS                       5000
#define BEACON_INTERVAL                 APP_TIMER_TICKS(UPDATE_MS)
APP_TIMER_DEF(m_beacon_timer_id);                                               // Timer ID
static volatile bool m_beacon_timer_flag = false;                               // Timer Flag

#define APP_SPIS_SCK_PIN 26
#define APP_SPIS_MOSI_PIN 29
#define APP_SPIS_MISO_PIN 30

#define APP_SPIS_CS_PIN 31

#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */

static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

//#define TEST_STRING_RS                 0x1E, 0x00, 0x00
//static uint8_t       m_tx_buf_rs[] = TEST_STRING_RS;    /**< TX buffer. */
//static uint8_t       m_rx_buf_rs[sizeof(TEST_STRING_RS) + 1];    /**< RX buffer. */
//static const uint8_t m_length_rs = sizeof(m_tx_buf_rs);        /**< Transfer length. */
uint8_t       *m_rx_buf_rs;

//#define TEST_STRING_RD                 0xA6, 0x00, 0x00
//static uint8_t       m_tx_buf_rd[] = TEST_STRING_RD;           /**< TX buffer. */
//static uint8_t       m_rx_buf_rd[sizeof(TEST_STRING_RD) + 1];    /**< RX buffer. */
//static const uint8_t m_length_rd = sizeof(m_tx_buf_rd);        /**< Transfer length. */
//uint8_t       m_rx_buf_rd[];
uint8_t       *m_rx_buf_rd;

#define BLE_GAP_EVENT_LENGTH_DEFAULT        (3)  /**< Default event length, in 1.25 ms units. */

/**@brief Receive MPS used by IPSP. */
#define BLE_IPSP_RX_MPS                                    50

/**@brief Maximum number of receive buffers.
 *
 * @details Maximum number of receive buffers to be used per IPSP channel.
 *          Each receive buffer is of size @ref BLE_IPSP_RX_BUFFER_SIZE.
 *          This configuration has implications on the number of SDUs that can
 *          be received while an SDU is being consumed by the application
 *          (6LoWPAN/IP Stack).
 */
#define BLE_IPSP_RX_BUFFER_COUNT                           4

/**@brief Transmission MPS used by IPSP.
 *
 * @note The actual MPS used is minimum of this value and the one requested by
 *       the peer during the channel setup. Here, the value used is
 *       (23 + 27 * 7).
 */
#define BLE_IPSP_TX_MPS                                    212

/**
 * @brief SPI user event handler.
 * @param event
 */
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    spi_xfer_done = true;
    NRF_LOG_INFO("Transfer completed.");
    if (m_rx_buf_rs[0] != 0) 
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(m_rx_buf_rs, strlen((const char *)m_rx_buf_rs));
    }
   if (m_rx_buf_rd[0] != 0) 
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(m_rx_buf_rd, strlen((const char *)m_rx_buf_rd));
    }

}

//****************************************************************************// 
// BLE FUNCTIONS
//****************************************************************************//
/**@brief Struct that contains pointers to the encoded advertising data. */
static ble_gap_adv_data_t m_adv_data =
{
    .adv_data =
    {
        .p_data = m_enc_advdata,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    },
    .scan_rsp_data =
    {
        .p_data = NULL,
        .len    = 0

    }
};


//static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
{
    APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                         // implementation.
    APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                         // manufacturer specific data in this implementation.
    APP_BEACON_UUID,     // 128 bit UUID value.
    APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
    APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
    APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                         // this implementation.
};


/**@brief Callback function for asserts in the SoftDevice.
 *
 * @details This function will be called in case of an assert in the SoftDevice.
 *
 * @warning This handler is an example only and does not fit a final product. You need to analyze
 *          how your product is supposed to react in case of Assert.
 * @warning On assert from the SoftDevice, the system can only recover on reset.
 *
 * @param[in]   line_num   Line number of the failing ASSERT call.
 * @param[in]   file_name  File name of the failing ASSERT call.
 */
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
    app_error_handler(DEAD_BEEF, line_num, p_file_name);
}

/**@brief Function for initializing the Advertising functionality.
 *
 * @details Encodes the required advertising data and passes it to the stack.
 *          Also builds a structure to be passed to the stack when starting advertising.
 */
static void advertising_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
    //uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

    ble_advdata_manuf_data_t manuf_specific_data;

    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
    // UICR instead of using the default values. The major and minor values obtained from the UICR
    // are encoded into advertising data in big endian order (MSB First).
    // To set the UICR used by this example to a desired value, write to the address 0x10001080
    // using the nrfjprog tool. The command to be used is as follows.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
    // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
    // the following command should be used.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
    uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
    uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);

    uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;

    m_beacon_info[index++] = MSB_16(major_value);
    m_beacon_info[index++] = LSB_16(major_value);

    m_beacon_info[index++] = MSB_16(minor_value);
    m_beacon_info[index++] = LSB_16(minor_value);
#endif

    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type             = BLE_ADVDATA_NO_NAME;
    advdata.flags                 = flags;
    advdata.p_manuf_specific_data = &manuf_specific_data;

    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    //m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
    m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
    m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    //m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
    m_adv_params.interval        = CONNECTABLE_ADV_INTERVAL;
    m_adv_params.duration        = 0;       // Never time out.
    //m_adv_params.duration        = 10;       // Never time out.
    

    m_adv_params.scan_req_notification = 1;   //VLS

    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    APP_ERROR_CHECK(err_code);
}

/**
 * @brief   Function for starting application timers.
 * @param   None.
 * @retval  None.
 */
static void application_timers_start(void)
{
	ret_code_t err_code;

	// Start application timers.
	err_code = app_timer_start(m_beacon_timer_id, BEACON_INTERVAL, NULL);
	APP_ERROR_CHECK(err_code);
}

/**@brief Function for starting advertising.
 */
static void advertising_start(void)
{
    ret_code_t err_code;
       
    err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    //err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_ADV_MODE_SLOW);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
    APP_ERROR_CHECK(err_code);
}


/**
 * @brief   Function for stopping advertising.
 * @param   None.
 * @retval  None.
 */
static void advertising_stop(void)
{
	ret_code_t err_code;

	err_code = sd_ble_gap_adv_stop(m_adv_handle);
	APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 * @param[in]   p_context   Unused.
 */
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t err_code;

    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_SCAN_REQ_REPORT: 
      NRF_LOG_INFO("RSSI %d",p_ble_evt->evt.gap_evt.params.scan_req_report.rssi);
      break;

    default:
      // No implementation needed.
      break;
    }
}

/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init(void)
{
    ret_code_t err_code;
    //ble_conn_cfg_t* conn_cfg;
    //ble_gap_cfg_t* gap_cfg_t;
    ble_cfg_t    ble_cfg;
    uint32_t     ram_start = 0;

    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    err_code = nrf_sdh_ble_app_ram_start_get(&ram_start);
    APP_ERROR_CHECK(err_code);

    // Configure the BLE stack using the default settings.
    // Fetch the start address of the application RAM.
    //err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    //APP_ERROR_CHECK(err_code);

    memset(&ble_cfg, 0, sizeof(ble_cfg));
  
    // Configure total number of connections.
    ble_cfg.conn_cfg.conn_cfg_tag                     = APP_BLE_CONN_CFG_TAG;
    ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count   = BLE_GAP_CONN_COUNT_DEFAULT * 2;
    ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT * 10;
    err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, ram_start);
    APP_ERROR_CHECK(err_code);

    /*memset(&ble_cfg, 0, sizeof(ble_cfg));

    ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = 256;
    err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, ram_start);
    APP_ERROR_CHECK(err_code);*/

    // Enable BLE stack.
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}


/**@brief Function for initializing the GATT module.
 */
/*static void gatt_init(void)
{
    ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
    APP_ERROR_CHECK(err_code);
}*/

/**@brief Function for initializing logging. */
static void log_init(void)
{
    ret_code_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();
}

/**@brief Function for initializing LEDs. */
static void leds_init(void)
{
    ret_code_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for initializing timers. */
static void timers_init(void)
{
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for initializing power management.
 */
static void power_management_init(void)
{
    ret_code_t err_code;
    err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling the idle state (main loop).
 *
 * @details If there is no pending log operation, then sleep until next the next event occurs.
 */
static void idle_state_handle(void)
{
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}

static void update_beacon_data(void)
{
    ret_code_t err_code;

    //#define TEST_STRING_RS                 0x1E, 0x00, 0x00
    static uint8_t       m_tx_buf_rs[] = {0x1E, 0x00, 0x00};
    m_rx_buf_rs = (uint8_t *)malloc(sizeof(m_tx_buf_rs));    /**< RX buffer. */
    free(m_rx_buf_rs);
    static uint8_t m_length_rs = sizeof(m_tx_buf_rs);        /**< Transfer length. */

    //#define TEST_STRING_RD                 0xA6, 0x00, 0x00
    static uint8_t       m_tx_buf_rd[] = {0xA6, 0x00, 0x00};           /**< TX buffer. */
    m_rx_buf_rd = (uint8_t *)malloc(sizeof(m_tx_buf_rd));    /**< RX buffer. */
    free(m_rx_buf_rd);
    static uint8_t m_length_rd = sizeof(m_tx_buf_rd);        /**< Transfer length. */
    
    // beacon update
    advertising_stop();
    
    nrf_gpio_cfg_output(APP_SPIS_CS_PIN);
    nrf_gpio_pin_set(APP_SPIS_CS_PIN);
        
    memset(m_rx_buf_rs, 0, m_length_rs);
    memset(m_rx_buf_rd, 0, m_length_rd);
    spi_xfer_done = false;
    
    err_code = nrf_drv_spi_transfer(&spi, m_tx_buf_rs, m_length_rs, m_rx_buf_rs, m_length_rs);
    APP_ERROR_CHECK(err_code);
    nrf_delay_ms(5);
    
    err_code = nrf_drv_spi_transfer(&spi, m_tx_buf_rd, m_length_rd, m_rx_buf_rd, m_length_rd);
    APP_ERROR_CHECK(err_code);
    //nrf_delay_ms(10);
    nrf_delay_ms(5);
    
    
    m_beacon_info[18] = m_rx_buf_rd[2];
    m_beacon_info[19] = m_rx_buf_rd[3];
    
    //m_beacon_info[18] = m_beacon_info[18] + 1;
    //m_beacon_info[19] = m_beacon_info[19] + 1;

    advertising_init();
    advertising_start();
}

/**
 * @brief Function for application main entry.
 */
int main(void)
{
    // Initialize.
    ret_code_t err_code;
    ble_advdata_t advdata;
    ble_advdata_manuf_data_t manuf_specific_data;

    //NRF_POWER->TASKS_CONSTLAT = 1;
    log_init();
    timers_init();
    leds_init();
    power_management_init();
    ble_stack_init();
    advertising_init();
    
    NRF_LOG_INIT(NULL);

    // Start execution.
    NRF_LOG_INFO("Beacon started.");
    //application_timers_start();
    advertising_start();

    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin   = APP_SPIS_CS_PIN;
    spi_config.miso_pin = APP_SPIS_MISO_PIN;
    spi_config.mosi_pin = APP_SPIS_MOSI_PIN;
    spi_config.sck_pin  = APP_SPIS_SCK_PIN;
    spi_config.frequency= NRF_DRV_SPI_FREQ_4M;
    err_code = nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);
    APP_ERROR_CHECK(err_code);

    //memset(m_rx_buf, 0, m_length);
    //spi_xfer_done = false;

    //APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length)); 
    /*while (!spis_xfer_done)
    {
        __WFE();
    }*/

    //APP_ERROR_CHECK(nrf_drv_spis_init(&spis_2, &spis_config, spis_event_handler2));
    // Enter main loop.
    for (;; )
    {
        idle_state_handle();
        update_beacon_data();
    }
}

I 'm developing with SDK 17.0.2. and combined BLE beacon sample and spis sample.

Also, I referred this QA.

Does anyone have ideas to solve this problem?

Kindly Regards,

Shigeto

Parents
  • To read data from a sensor you need to use SPI master (SPIM), the sensor will be the SPI slave (SPIS).

    Kenneth

  • Hi,

    I noticed that my pin assigns ware wrong. So does wire connections between BLE and sensor.

     I fixed them and debugged the program.

    However, both m_rx_buf_rd and m_rx_buf_rs got just null...

    Does it mean that the sensor detect zero pressure on?? Or something's still wrong?

    If something's wrong, would you let me know knacks to solve this kind of problem, please?

    BTW, Below is slightly amended code.

    #include <stdbool.h>
    #include <stdint.h>
    #include "nordic_common.h"
    #include "bsp.h"
    #include "nrf_soc.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "ble_advdata.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrf_drv_spi.h"
    #include "ble_advertising.h"
    #include "ble_gap.h"
    
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    
    #include "nrf_spi_mngr.h"
    
    #include "sdk_config.h"
    #include "nrf_drv_spis.h"
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    
    #if defined (LEGACY_DEFINE)
    
    #undef NRFX_DEFINE
    #define NRFX_DEFINE LEGACY_DEFINE
    
    #endif 
    
    
    #define APP_BLE_CONN_CFG_TAG            1                                  /**< A tag identifying the SoftDevice BLE configuration. */
    #define APP_BLE_OBSERVER_PRIO           3                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    //#define APP_BLE_OBSERVER_PRIO           1                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    
    //#define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    //#define CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_1_25_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    #define CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(12500, UNIT_1_25_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    
    #define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */
    
    #define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */
    
    #define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
    #define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
    
    //#define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
    #define APP_COMPANY_IDENTIFIER          0x004C                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
    #define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
    #define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
    #define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                            0x45, 0x56, 0x67, 0x78, \
                                            0x89, 0x9a, 0xab, 0xbc, \
                                            0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */
                
    #define APP_SIGNAL_OUT                  0xc3                              /**< Proprietary SIGNAL OUT for Beacon. */
    
    #define DEAD_BEEF                       0xDEADBEEF                         /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    #define MAJ_VAL_OFFSET_IN_BEACON_INFO   18                                 /**< Position of the MSB of the Major Value in m_beacon_info array. */
    #define UICR_ADDRESS                    0x10001080                         /**< Address of the UICR register used by this example. The major and minor versions to be encoded into the advertising data will be picked up from this location. */
    #endif
    
    static ble_gap_adv_params_t m_adv_params;                                  /**< Parameters to be passed to the stack when starting advertising. */
    static uint8_t              m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
    static uint8_t              m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded advertising set. */
    
    //NRF_BLE_GATT_DEF(m_gatt);                                                       /**< GATT module instance. */
    
    #define UPDATE_MS                       5000
    #define BEACON_INTERVAL                 APP_TIMER_TICKS(UPDATE_MS)
    APP_TIMER_DEF(m_beacon_timer_id);                                               // Timer ID
    static volatile bool m_beacon_timer_flag = false;                               // Timer Flag
    
    #define APP_SPIS_SCK_PIN 26
    #define APP_SPIS_MOSI_PIN 29
    #define APP_SPIS_MISO_PIN 28
    
    #define APP_SPIS_CS_PIN 31
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    
    #define TEST_STRING_RS                 {0x1E, 0x00, 0x00}
    static uint8_t       m_tx_buf_rs[] = TEST_STRING_RS;    /**< TX buffer. */
    //static uint8_t       m_rx_buf_rs[sizeof(TEST_STRING_RS) + 1];    /**< RX buffer. */
    static uint8_t       m_rx_buf_rs[sizeof(m_tx_buf_rs) + 1];    /**< RX buffer. */
    static const uint8_t m_length_rs = sizeof(m_tx_buf_rs);        /**< Transfer length. */
    //uint8_t       *m_rx_buf_rs;
    
    #define TEST_STRING_RD                 {0xA6, 0x00, 0x00}
    static uint8_t       m_tx_buf_rd[] = TEST_STRING_RD;           /**< TX buffer. */
    //static uint8_t       m_rx_buf_rd[sizeof(TEST_STRING_RD) + 1];    /**< RX buffer. */
    static uint8_t       m_rx_buf_rd[sizeof(m_tx_buf_rd) + 1];    /**< RX buffer. */
    static const uint8_t m_length_rd = sizeof(m_tx_buf_rd);        /**< Transfer length. */
    //uint8_t       m_rx_buf_rd[];
    //uint8_t       *m_rx_buf_rd;
    
    #define BLE_GAP_EVENT_LENGTH_DEFAULT        (3)  /**< Default event length, in 1.25 ms units. */
    
    /**@brief Receive MPS used by IPSP. */
    #define BLE_IPSP_RX_MPS                                    50
    
    /**@brief Maximum number of receive buffers.
     *
     * @details Maximum number of receive buffers to be used per IPSP channel.
     *          Each receive buffer is of size @ref BLE_IPSP_RX_BUFFER_SIZE.
     *          This configuration has implications on the number of SDUs that can
     *          be received while an SDU is being consumed by the application
     *          (6LoWPAN/IP Stack).
     */
    #define BLE_IPSP_RX_BUFFER_COUNT                           4
    
    /**@brief Transmission MPS used by IPSP.
     *
     * @note The actual MPS used is minimum of this value and the one requested by
     *       the peer during the channel setup. Here, the value used is
     *       (23 + 27 * 7).
     */
    #define BLE_IPSP_TX_MPS                                    212
    
    /**
     * @brief SPI user event handler.
     * @param event
     */
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf_rs[0] != 0) 
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf_rs, strlen((const char *)m_rx_buf_rs));
        }
       if (m_rx_buf_rd[0] != 0) 
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf_rd, strlen((const char *)m_rx_buf_rd));
        }
    
    }
    
    //****************************************************************************// 
    // BLE FUNCTIONS
    //****************************************************************************//
    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = NULL,
            .len    = 0
    
        }
    };
    
    
    //static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
    uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
    {
        APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                             // implementation.
        APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                             // manufacturer specific data in this implementation.
        APP_BEACON_UUID,     // 128 bit UUID value.
        APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
        APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
        APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                             // this implementation.
    };
    
    
    /**@brief Callback function for asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in]   line_num   Line number of the failing ASSERT call.
     * @param[in]   file_name  File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    /**@brief Function for initializing the Advertising functionality.
     *
     * @details Encodes the required advertising data and passes it to the stack.
     *          Also builds a structure to be passed to the stack when starting advertising.
     */
    static void advertising_init(void)
    {
        uint32_t      err_code;
        ble_advdata_t advdata;
        uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
        //uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        ble_advdata_manuf_data_t manuf_specific_data;
    
        manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
        // UICR instead of using the default values. The major and minor values obtained from the UICR
        // are encoded into advertising data in big endian order (MSB First).
        // To set the UICR used by this example to a desired value, write to the address 0x10001080
        // using the nrfjprog tool. The command to be used is as follows.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
        // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
        // the following command should be used.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
        uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
        uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);
    
        uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;
    
        m_beacon_info[index++] = MSB_16(major_value);
        m_beacon_info[index++] = LSB_16(major_value);
    
        m_beacon_info[index++] = MSB_16(minor_value);
        m_beacon_info[index++] = LSB_16(minor_value);
    #endif
    
        manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
        manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type             = BLE_ADVDATA_NO_NAME;
        advdata.flags                 = flags;
        advdata.p_manuf_specific_data = &manuf_specific_data;
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        //m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
        m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        //m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
        m_adv_params.interval        = CONNECTABLE_ADV_INTERVAL;
        m_adv_params.duration        = 0;       // Never time out.
        //m_adv_params.duration        = 10;       // Never time out.
        
    
        m_adv_params.scan_req_notification = 1;   //VLS
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief   Function for starting application timers.
     * @param   None.
     * @retval  None.
     */
    static void application_timers_start(void)
    {
    	ret_code_t err_code;
    
    	// Start application timers.
    	err_code = app_timer_start(m_beacon_timer_id, BEACON_INTERVAL, NULL);
    	APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for starting advertising.
     */
    static void advertising_start(void)
    {
        ret_code_t err_code;
           
        err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
        //err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_ADV_MODE_SLOW);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief   Function for stopping advertising.
     * @param   None.
     * @retval  None.
     */
    static void advertising_stop(void)
    {
    	ret_code_t err_code;
    
    	err_code = sd_ble_gap_adv_stop(m_adv_handle);
    	APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
        case BLE_GAP_EVT_SCAN_REQ_REPORT: 
          NRF_LOG_INFO("RSSI %d",p_ble_evt->evt.gap_evt.params.scan_req_report.rssi);
          break;
    
        default:
          // No implementation needed.
          break;
        }
    }
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
        //ble_conn_cfg_t* conn_cfg;
        //ble_gap_cfg_t* gap_cfg_t;
        ble_cfg_t    ble_cfg;
        uint32_t     ram_start = 0;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_sdh_ble_app_ram_start_get(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        //err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        //APP_ERROR_CHECK(err_code);
    
        memset(&ble_cfg, 0, sizeof(ble_cfg));
      
        // Configure total number of connections.
        ble_cfg.conn_cfg.conn_cfg_tag                     = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count   = BLE_GAP_CONN_COUNT_DEFAULT * 2;
        ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT * 10;
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);
    
        /*memset(&ble_cfg, 0, sizeof(ble_cfg));
    
        ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = 256;
        err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);*/
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for initializing the GATT module.
     */
    /*static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }*/
    
    /**@brief Function for initializing logging. */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    /**@brief Function for initializing LEDs. */
    static void leds_init(void)
    {
        ret_code_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing timers. */
    static void timers_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    static void update_beacon_data(void)
    {
        ret_code_t err_code;
    
        //#define TEST_STRING_RS                 0x1E, 0x00, 0x00
        //static uint8_t       m_tx_buf_rs[] = {0x1E, 0x00, 0x00};
        //m_rx_buf_rs = (uint8_t *)malloc(sizeof(m_tx_buf_rs));    /**< RX buffer. */
        //free(m_rx_buf_rs);
        //static uint8_t m_length_rs = sizeof(m_tx_buf_rs);        /**< Transfer length. */
    
        //#define TEST_STRING_RD                 0xA6, 0x00, 0x00
        //static uint8_t       m_tx_buf_rd[] = {0xA6, 0x00, 0x00};           /**< TX buffer. */
        //m_rx_buf_rd = (uint8_t *)malloc(sizeof(m_tx_buf_rd));    /**< RX buffer. */
        //free(m_rx_buf_rd);
        //static uint8_t m_length_rd = sizeof(m_tx_buf_rd);        /**< Transfer length. */
        
        // beacon update
        advertising_stop();
        
        nrf_gpio_cfg_output(APP_SPIS_CS_PIN);
        nrf_gpio_pin_set(APP_SPIS_CS_PIN);
            
        memset(m_rx_buf_rs, 0, m_length_rs);
        memset(m_rx_buf_rd, 0, m_length_rd);
        
        spi_xfer_done = false;
        
        err_code = nrf_drv_spi_transfer(&spi, m_tx_buf_rs, m_length_rs, m_rx_buf_rs, m_length_rs);
        APP_ERROR_CHECK(err_code);
        nrf_delay_ms(10);
        
        err_code = nrf_drv_spi_transfer(&spi, m_tx_buf_rd, m_length_rd, m_rx_buf_rd, m_length_rd);
        APP_ERROR_CHECK(err_code);
        //nrf_delay_ms(10);
        nrf_delay_ms(10);
        
        
        m_beacon_info[18] = m_rx_buf_rd[2];
        m_beacon_info[19] = m_rx_buf_rd[3];
        
        //m_beacon_info[18] = m_beacon_info[18] + 1;
        //m_beacon_info[19] = m_beacon_info[19] + 1;
    
        advertising_init();
        advertising_start();
    }
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        // Initialize.
        ret_code_t err_code;
        ble_advdata_t advdata;
        ble_advdata_manuf_data_t manuf_specific_data;
    
        //NRF_POWER->TASKS_CONSTLAT = 1;
        log_init();
        timers_init();
        leds_init();
        power_management_init();
        ble_stack_init();
        advertising_init();
        
        NRF_LOG_INIT(NULL);
    
        // Start execution.
        NRF_LOG_INFO("Beacon started.");
        //application_timers_start();
        advertising_start();
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin   = APP_SPIS_CS_PIN;
        spi_config.miso_pin = APP_SPIS_MISO_PIN;
        spi_config.mosi_pin = APP_SPIS_MOSI_PIN;
        spi_config.sck_pin  = APP_SPIS_SCK_PIN;
        spi_config.frequency= NRF_DRV_SPI_FREQ_4M;
        err_code = nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        //memset(m_rx_buf, 0, m_length);
        //spi_xfer_done = false;
    
        //APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length)); 
        /*while (!spis_xfer_done)
        {
            __WFE();
        }*/
    
        //APP_ERROR_CHECK(nrf_drv_spis_init(&spis_2, &spis_config, spis_event_handler2));
        // Enter main loop.
        for (;; )
        {
            idle_state_handle();
            update_beacon_data();
        }
    }

    Kindly Regards,

    Shigeto

  • You need some way of finding out what is sent on the SPI interface. Do you by any chance have access to a logic analyzer or oscilloscope so you may observe the SPI pins? Alternatively can you connect MOSI to MISO, and check that data sent in tx_buf is received on rx_buf after transfer is finished?

    Kenneth

Reply Children
Related