/**
 * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 *
 * @defgroup ble_sdk_uart_over_ble_main main.c
 * @{
 * @ingroup  ble_sdk_app_nus_eval
 * @brief    UART over BLE application main file.
 *
 * This file contains the source code for a sample application that uses the Nordic UART service.
 * This application uses the @ref srvlib_conn_params module.
 */


#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "ble_hci.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "app_timer.h"
#include "ble_nus.h"
#include "app_uart.h"
#include "app_util_platform.h"
#include "bsp_btn_ble.h"
#include "nrf_pwr_mgmt.h"

#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include <stdbool.h>
#include <stdint.h>
#include "nrf_drv_timer.h"
#include "bsp.h"

#include "lsm9ds1_reg.h"
#include "nrf_drv_gpiote.h"






#define APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */

#define DEVICE_NAME                     "Nordic_UART_P"                               /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */

#define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */

#define APP_ADV_INTERVAL                64                                          /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */

#define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(20, UNIT_1_25_MS)             /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(75, UNIT_1_25_MS)             /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY                   0                                           /**< Slave latency. */
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                           /**< Number of attempts before giving up the connection parameter negotiation. */

#define DEAD_BEEF                       0xDEADBEEF                                  /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */

#define UART_TX_BUF_SIZE                256//1024//2048                                      /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE                256//1024//2048                                      /**< UART RX buffer size. */

typedef union {
  int16_t i16bit[3];
  uint8_t u8bit[6];
} axis3bit16_t;



static axis3bit16_t data_raw_acceleration;
static axis3bit16_t data_raw_angular_rate;
static axis3bit16_t data_raw_magnetic_field;
static float acceleration_mg[3];
static float angular_rate_mdps[3];
static float magnetic_field_mgauss[3];
static lsm9ds1_id_t whoamI;
static lsm9ds1_status_t reg;
static uint8_t rst;
static void advertising_start(void);
//char tx_buffer[100];

//uint8_t sample_a_float[60][6];
//uint8_t sample_g_float[60][6];

int8_t status=0;
int8_t status_connected=0;
uint8_t ble_tx_buffer_acc[500];
uint16_t ble_tx_buffer_acc_len=0;

uint8_t ble_tx_buffer_ang[500];
uint16_t ble_tx_buffer_ang_len=0;
uint16_t counter_flag=0;
int8_t rssi_value=0;

#define DEBUG_FIFO_SIZE_INSIDE
//#define DEBUG_BLE_SEND_DEBUG


//#define DEBUG_SPI_BUFFER_INSIDE

//#define WATCHDOG_ENABLE


#define SHORT_RANGE_ENABLE
//#define LONG_RANGE_ENABLE

//#define BLE_UART_RECEIVE_ENABLE
//#define LONG_RANGE_HIGH_SPEED
//#define LONG_RANGE_HIGH_SPEED_BLE_STREAMING_SLOW
 


static void interrupt_pin_init(void);
void LSM9DS1_start(void);
void in_pin_handler(void);


BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);                                   /**< BLE NUS service instance. */
NRF_BLE_GATT_DEF(m_gatt);                                                           /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr);                                                             /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */
static uint16_t   m_conn_handle          = BLE_CONN_HANDLE_INVALID;                 /**< Handle of the current connection. */
static uint16_t   m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3;            /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
{
    {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};


/**@brief Function for assert macro callback.
 *
 * @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 analyse
 *          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] p_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 timer module.
 */
static void timers_init(void)
{
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for the GAP initialization.
 *
 * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
 *          the device. It also sets the permissions and appearance.
 */
static void gap_params_init(void)
{
    uint32_t                err_code;
    ble_gap_conn_params_t   gap_conn_params;
    ble_gap_conn_sec_mode_t sec_mode;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *) DEVICE_NAME,
                                          strlen(DEVICE_NAME));
    APP_ERROR_CHECK(err_code);

    memset(&gap_conn_params, 0, sizeof(gap_conn_params));

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling Queued Write Module errors.
 *
 * @details A pointer to this function will be passed to each service which may need to inform the
 *          application about an error.
 *
 * @param[in]   nrf_error   Error code containing information about what went wrong.
 */
static void nrf_qwr_error_handler(uint32_t nrf_error)
{
    APP_ERROR_HANDLER(nrf_error);
}


/**@brief Function for handling the data from the Nordic UART Service.
 *
 * @details This function will process the data received from the Nordic UART BLE Service and send
 *          it to the UART module.
 *
 * @param[in] p_evt       Nordic UART Service event.
 */
/**@snippet [Handling the data received over BLE] */
static void nus_data_handler(ble_nus_evt_t * p_evt)
{

    if (p_evt->type == BLE_NUS_EVT_RX_DATA)
    {
        uint32_t err_code;

        //NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
        //NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
        #ifdef BLE_UART_RECEIVE_ENABLE
        printf("RecBLE_UART");nrf_delay_ms(1);
         
        for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
        {
            do
            {
                err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
                if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
                {
                    NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                    APP_ERROR_CHECK(err_code);
                }
            } while (err_code == NRF_ERROR_BUSY);
        }
        if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
        {
            while (app_uart_put('\n') == NRF_ERROR_BUSY);
        }
        #endif
        
    }

}
/**@snippet [Handling the data received over BLE] */


/**@brief Function for initializing services that will be used by the application.
 */
static void services_init(void)
{
    uint32_t           err_code;
    ble_nus_init_t     nus_init;
    nrf_ble_qwr_init_t qwr_init = {0};

    // Initialize Queued Write Module.
    qwr_init.error_handler = nrf_qwr_error_handler;

    err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
    APP_ERROR_CHECK(err_code);

    // Initialize NUS.
    memset(&nus_init, 0, sizeof(nus_init));

    nus_init.data_handler = nus_data_handler;

    err_code = ble_nus_init(&m_nus, &nus_init);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling an event from the Connection Parameters Module.
 *
 * @details This function will be called for all events in the Connection Parameters Module
 *          which are passed to the application.
 *
 * @note All this function does is to disconnect. This could have been done by simply setting
 *       the disconnect_on_fail config parameter, but instead we use the event handler
 *       mechanism to demonstrate its use.
 *
 * @param[in] p_evt  Event received from the Connection Parameters Module.
 */
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
    uint32_t err_code;

    if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
    {
        err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
        APP_ERROR_CHECK(err_code);
    }
}


/**@brief Function for handling errors from the Connection Parameters module.
 *
 * @param[in] nrf_error  Error code containing information about what went wrong.
 */
static void conn_params_error_handler(uint32_t nrf_error)
{
    APP_ERROR_HANDLER(nrf_error);
}


/**@brief Function for initializing the Connection Parameters module.
 */
static void conn_params_init(void)
{
    uint32_t               err_code;
    ble_conn_params_init_t cp_init;

    memset(&cp_init, 0, sizeof(cp_init));

    cp_init.p_conn_params                  = NULL;
    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
    cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
    cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
    cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
    cp_init.disconnect_on_fail             = false;
    cp_init.evt_handler                    = on_conn_params_evt;
    cp_init.error_handler                  = conn_params_error_handler;

    err_code = ble_conn_params_init(&cp_init);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for putting the chip into sleep mode.
 *
 * @note This function will not return.
 */
static void sleep_mode_enter(void)
{
    uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    APP_ERROR_CHECK(err_code);

    // Prepare wakeup buttons.
    err_code = bsp_btn_ble_sleep_mode_prepare();
    APP_ERROR_CHECK(err_code);

    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    err_code = sd_power_system_off();
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling advertising events.
 *
 * @details This function will be called for advertising events which are passed to the application.
 *
 * @param[in] ble_adv_evt  Advertising event.
 */
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
    uint32_t err_code;

    switch (ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;
        case BLE_ADV_EVT_IDLE:
            sleep_mode_enter();
            break;
        default:
            break;
    }
}


/**@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)
{
    uint32_t err_code;
	int8_t tx_power = 8; //niklas

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            //NRF_LOG_INFO("Connected"); 
	    status=1;
	    status_connected=1;
	    printf("Connect");nrf_delay_ms(1);
            
            //interrupt_pin_init();//niklas
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            //reference https://jimmywongiot.com/2019/11/30/how-to-get-the-rssi-change-on-the-nrf5-sdk/
            //https://devzone.nordicsemi.com/f/nordic-q-a/69366/regarding-about-the-connection-rssi-for-signal-strength
            err_code = sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,1,2);//niklas
            APP_ERROR_CHECK(err_code);

            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);
	    //err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_conn_handle, tx_power); //niklas
	    //APP_ERROR_CHECK(err_code);
            break;

        //case BLE_GAP_EVT_RSSI_CHANGED:
        //     rssi_value=p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
        //     printf("RSSI=%d\n",p_ble_evt->evt.gap_evt.params.rssi_changed.rssi);

        case BLE_GAP_EVT_DISCONNECTED:
	    status=2;
	    status_connected=2;
            //NRF_LOG_INFO("Disconnected");
	    printf("Disc");nrf_delay_ms(1);
            //interrupt_pin_init();//niklas
			
            // LED indication will be changed when advertising starts.
            m_conn_handle = BLE_CONN_HANDLE_INVALID;

			if(nrf_gpio_pin_read(PIN_INTERRUPT))
			{ 
			 printf("In AA");nrf_delay_ms(1);
			 //in_pin_handler();
			}
            advertising_start();

            break;

        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            status=3;
            //NRF_LOG_DEBUG("PHY update request.");
            printf("PHY update request.");nrf_delay_ms(1);
            
            ble_gap_phys_t const phys =
            {

            #ifdef LONG_RANGE_ENABLE
                .rx_phys = BLE_GAP_PHY_CODED,//BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_CODED,//BLE_GAP_PHY_AUTO,
            #endif

            #ifdef SHORT_RANGE_ENABLE
                .rx_phys = BLE_GAP_PHY_1MBPS,//BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_1MBPS,//BLE_GAP_PHY_AUTO,
            #endif

            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
		     status=5;
            // Pairing not supported
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
		    status=6;
            // No system attributes have been stored.
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
			status=7;
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_TIMEOUT:
		    status=8;
            // Disconnect on GATT Server timeout event.
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;

        default:
		    status=9;
            // No implementation needed.
            break;
    }
}


/**@brief Function for the SoftDevice initialization.
 *
 * @details This function initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init(void)
{
    ret_code_t err_code;

    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    // Configure the BLE stack using the default settings.
    // Fetch the start address of the application RAM.
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &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 handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
    if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
    {
        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
        NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    }
    NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
                  p_gatt->att_mtu_desired_central,
                  p_gatt->att_mtu_desired_periph);
}


/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
    ret_code_t err_code;

    err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling events from the BSP module.
 *
 * @param[in]   event   Event generated by button press.
 */
void bsp_event_handler(bsp_event_t event)
{
    uint32_t err_code;
    switch (event)
    {
        case BSP_EVENT_SLEEP:
            sleep_mode_enter();
            break;

        case BSP_EVENT_DISCONNECT:
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BSP_EVENT_WHITELIST_OFF:
            if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
            {
                err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
            }
            break;

        default:
            break;
    }
}


/**@brief   Function for handling app_uart events.
 *
 * @details This function will receive a single character from the app_uart module and append it to
 *          a string. The string will be be sent over BLE when the last character received was a
 *          'new line' '\n' (hex 0x0A) or if the string has reached the maximum data length.
 */
/**@snippet [Handling the data received over UART] */
void uart_event_handle(app_uart_evt_t * p_event)
{
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;

    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            index++;

            if ((data_array[index - 1] == '\n') ||
                (data_array[index - 1] == '\r') ||
                (index >= m_ble_nus_max_data_len))
            {
                if (index > 1)
                {
                    //NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                    //NRF_LOG_HEXDUMP_DEBUG(data_array, index);
                    printf("Ready over BLE NUS \n"); nrf_delay_ms(1);
                    do
                    {
                        uint16_t length = (uint16_t)index;
                        err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
                        if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        }
                    } while (err_code == NRF_ERROR_RESOURCES);
                }

                index = 0;
            }
            break;

        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}
/**@snippet [Handling the data received over UART] */


/**@brief  Function for initializing the UART module.
 */
/**@snippet [UART Initialization] */
static void uart_init(void)
{
    uint32_t                     err_code;
    app_uart_comm_params_t const comm_params =
    {
        .rx_pin_no    = RX_PIN_NUMBER,
        .tx_pin_no    = TX_PIN_NUMBER,
        .rts_pin_no   = RTS_PIN_NUMBER,
        .cts_pin_no   = CTS_PIN_NUMBER,
        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
        .use_parity   = false,
#if defined (UART_PRESENT)
        .baud_rate    = NRF_UART_BAUDRATE_115200
#else
        .baud_rate    = NRF_UARTE_BAUDRATE_115200
#endif
    };

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_event_handle,
                       APP_IRQ_PRIORITY_LOW,//APP_IRQ_PRIORITY_HIGH,//APP_IRQ_PRIORITY_HIGHEST,// APP_IRQ_PRIORITY_LOWEST,
                       err_code);
    APP_ERROR_CHECK(err_code);
}
/**@snippet [UART Initialization] */


/**@brief Function for initializing the Advertising functionality.*/

#ifdef SHORT_RANGE_ENABLE
static void advertising_init(void)
{
    uint32_t               err_code;
    ble_advertising_init_t init;
    int8_t tx_power = 8; //niklas

    memset(&init, 0, sizeof(init));

    init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;
    init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    //init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

    init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.srdata.uuids_complete.p_uuids  = m_adv_uuids;

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    //init.config.ble_adv_primary_phy       = BLE_GAP_PHY_CODED;
    //init.config.ble_adv_secondary_phy     = BLE_GAP_PHY_CODED;
    //init.config.ble_adv_extended_enabled  = true; 
    init.evt_handler = on_adv_evt;
    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);

    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV , m_advertising.adv_handle, tx_power);
    APP_ERROR_CHECK(err_code);
}
#endif

//niklas

#ifdef LONG_RANGE_ENABLE
static void advertising_init(void)
{
    ret_code_t             err_code;
    int8_t tx_power = 8; //niklas
	  //??????????????
    ble_advertising_init_t init;
    //???????
    memset(&init, 0, sizeof(init));
    //??????:??
    init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
	  //??????:???
    init.advdata.include_appearance      = false;
	  //Flag:???????,???BR/EDR
    init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
	  //UUID
    init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    init.config.ble_adv_fast_enabled      = true;//???????????
    init.config.ble_adv_fast_interval     = APP_ADV_INTERVAL;//?????????????
    init.config.ble_adv_fast_timeout      = APP_ADV_DURATION;
    
    
    //init.config.ble_adv_primary_phy       = BLE_GAP_PHY_CODED;
    //init.config.ble_adv_secondary_phy     = BLE_GAP_PHY_CODED;


     init.config.ble_adv_primary_phy       = BLE_GAP_PHY_CODED;
     init.config.ble_adv_secondary_phy     = BLE_GAP_PHY_CODED;
     init.config.ble_adv_extended_enabled  = true; 
 


    //init.config.ble_adv_extended_enabled  = true; 
    init.evt_handler = on_adv_evt;
    init.evt_handler = on_adv_evt;//????????
    //?????
    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);
    //?????????APP_BLE_CONN_CFG_TAG????????????,????????????,????SoftDevice???,
		//????sd_ble_gap_adv_set_configure()????????
		//??SoftDevice??(S140 V7.0.1??)???????????1,??APP_BLE_CONN_CFG_TAG???1?
    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);

    //niklas
    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV , m_advertising.adv_handle, tx_power);
    APP_ERROR_CHECK(err_code);


}
#endif

/**@brief Function for initializing buttons and leds.
 *
 * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
 */
static void buttons_leds_init(bool * p_erase_bonds)
{
    bsp_event_t startup_event;

    uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_btn_ble_init(NULL, &startup_event);
    APP_ERROR_CHECK(err_code);

    *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}


/**@brief Function for initializing the nrf log module.
 */
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 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();
    }
}


/**@brief Function for starting advertising.
*/

static void advertising_start(void)
{
    uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for starting advertising. */
/*
static void advertising_start(void)
{
    static ble_gap_adv_params_t adv_params = {0};
    
    adv_params.properties.connectable = 1;
    // Setting up the scan response packet is currently not supported when using CODED phy
    adv_params.properties.scannable = 0;    
    adv_params.properties.legacy_pdu = 0;
    adv_params.p_peer_addr   = NULL;
    adv_params.fp            = BLE_GAP_ADV_FP_ANY;
    adv_params.interval      = APP_ADV_INTERVAL;
    adv_params.duration      = APP_ADV_TIMEOUT_IN_SECONDS * 100;
#if defined(S140)
    adv_params.primary_phy   = BLE_GAP_PHY_CODED;
    adv_params.secondary_phy = BLE_GAP_PHY_CODED;
#else
    adv_params.primary_phy   = BLE_GAP_PHY_1MBPS;
    adv_params.secondary_phy = BLE_GAP_PHY_1MBPS;
#endif

    NRF_LOG_INFO("Starting advertising.");

    ret_code_t err_code = sd_ble_gap_adv_start(BLE_GAP_ADV_SET_HANDLE_DEFAULT, &adv_params, APP_BLE_CONN_CFG_TAG);
    APP_ERROR_CHECK(err_code);
}

*/


//P3 to do 
void niklas_ble_send_handler(void)
{
	static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;
	//printf("Status=%d\n",status);nrf_delay_ms(1);
	
	index=7;
	data_array[0]='0';
	data_array[1]='1';
	data_array[2]='2';
	data_array[3]='3';
	data_array[4]='4';
	data_array[5]='5';
	data_array[6]='\n';
	
  do
  {
      uint16_t length = (uint16_t)index;
      err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
      if ((err_code != NRF_ERROR_INVALID_STATE) &&
          (err_code != NRF_ERROR_RESOURCES) &&
          (err_code != NRF_ERROR_NOT_FOUND))
      {
          APP_ERROR_CHECK(err_code);
      }
  } while (err_code == NRF_ERROR_RESOURCES);
}


//P3 to do 
void niklas_ble_send_array_handler(void)
{
  uint32_t       err_code;
  #ifdef DEBUG_BLE_SEND_DEBUG
  printf("G1 \r\n");nrf_delay_ms(1);
  #endif
  if(ble_tx_buffer_acc_len<BLE_NUS_MAX_DATA_LEN)
  {
     do
     {
     
         err_code = ble_nus_data_send(&m_nus, ble_tx_buffer_acc, &ble_tx_buffer_acc_len, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) &&
             (err_code != NRF_ERROR_RESOURCES) &&
             (err_code != NRF_ERROR_NOT_FOUND))
         {
             APP_ERROR_CHECK(err_code);
         }
     } while (err_code == NRF_ERROR_RESOURCES);	  
  }

  #ifdef DEBUG_BLE_SEND_DEBUG
  printf("G2 \r\n");nrf_delay_ms(1);
  #endif
  if(ble_tx_buffer_acc_len<BLE_NUS_MAX_DATA_LEN)
  {  
     do
     {
         
         err_code = ble_nus_data_send(&m_nus, ble_tx_buffer_ang, &ble_tx_buffer_ang_len, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) &&
             (err_code != NRF_ERROR_RESOURCES) &&
             (err_code != NRF_ERROR_NOT_FOUND))
         {
             APP_ERROR_CHECK(err_code);
         }
     } while (err_code == NRF_ERROR_RESOURCES);
  }
  #ifdef DEBUG_BLE_SEND_DEBUG 
  printf("G3 \r\n");nrf_delay_ms(1);
  #endif
}





static lsm9ds1_id_t whoamI;
static lsm9ds1_status_t reg;
static uint8_t rst;
//char tx_buffer[100];

uint8_t register_address = 0x0F;    //Address of the who am i register to be read

#define SPI_INSTANCE  0 

uint8_t spi_add_mag = IMU_CS_M_PIN;
stmdev_ctx_t dev_ctx_mag;

uint8_t spi_add_imu = IMU_CS_AG_PIN;
stmdev_ctx_t dev_ctx_imu;




//uint8_t   SPI_Tx_Buf[SPI_BUFSIZE];
//uint8_t   SPI_Rx_Buf[SPI_BUFSIZE];
//volatile  uint8_t   SPIReadLength, SPIWriteLength;
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
//static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); 
//SPI事件处理函数，该函数中置位传输完成标志spi_xfer_done
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    spi_xfer_done = true;
}

static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len){
	
   uint8_t *spi_address = handle;
   #ifdef DEBUG_SPI_BUFFER_INSIDE
   printf("\nRpin=%d\n",*spi_address);nrf_delay_ms(1);
   printf("            reg=%2x\n",reg);nrf_delay_ms(1);
   #endif
   if(*spi_address==IMU_CS_M_PIN){nrf_gpio_pin_clear(IMU_CS_M_PIN); }
   if(*spi_address==IMU_CS_AG_PIN){nrf_gpio_pin_clear(IMU_CS_AG_PIN);}

  
   uint8_t temp_tx_buf[10];
   uint8_t temp_rx_buf[10];
   int32_t ret;
   memset(temp_tx_buf,0x00,sizeof(temp_tx_buf));
   memset(temp_tx_buf,0x00,sizeof(temp_rx_buf));
   temp_tx_buf[0]=(reg | 0x80);
   for (uint8_t i = 0; i < len; i++) {
      temp_tx_buf[i+1] = 0x00;
    }
   spi_xfer_done = false;
   
    #ifdef DEBUG_SPI_BUFFER_INSIDE
	printf("00t_tx_buf=%2x\n",temp_tx_buf[0]);//app_uart_flush();
    printf("01t_tx_buf=%2x\n",temp_tx_buf[1]);//app_uart_flush();
    nrf_delay_ms(1);
    #endif
   
   
   ret=nrf_drv_spi_transfer(&spi, temp_tx_buf, 2, temp_rx_buf, len+1);
   
   APP_ERROR_CHECK(ret);
   while(spi_xfer_done == false){};
    

   #ifdef DEBUG_SPI_BUFFER_INSIDE
   printf("02t_rx_buf len=%d \n",len);//app_uart_flush();
   #endif
   for (uint8_t i = 0; i < len; i++) {

	  bufp[i]=temp_rx_buf[i+1];
	  #ifdef DEBUG_SPI_BUFFER_INSIDE
      printf("C0%d temp_rx_buf=%02x\n",i+1,temp_rx_buf[i] );nrf_delay_ms(1);
	  #endif
   }

    *bufp = temp_rx_buf[1];

  if(*spi_address==IMU_CS_M_PIN){nrf_gpio_pin_set(IMU_CS_M_PIN); }
  if(*spi_address==IMU_CS_AG_PIN){nrf_gpio_pin_set(IMU_CS_AG_PIN); }
  return 0;
}




static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len){
   uint8_t *spi_address = handle;
   
   #ifdef DEBUG_SPI_BUFFER_INSIDE
   printf("\nTpin=%d\n",*spi_address);nrf_delay_ms(1);
   printf("            reg=%2x\n",reg);nrf_delay_ms(1);
   printf("A00 bufp=%2x\n",bufp[0]);nrf_delay_ms(1);
   printf("A01 bufp=%2x\n",bufp[1]);nrf_delay_ms(1);
   printf("B00 bufp=%x\n",*bufp);nrf_delay_ms(1);
   #endif

   //printf("TPIN is %d\r\n",*spi_address);
   if(*spi_address==IMU_CS_M_PIN){nrf_gpio_pin_clear(IMU_CS_M_PIN); }
   if(*spi_address==IMU_CS_AG_PIN){nrf_gpio_pin_clear(IMU_CS_AG_PIN);}

   uint8_t temp_tx_buf[10];
   uint8_t temp_rx_buf[10];
   memset(temp_tx_buf,0x00,sizeof(temp_tx_buf));
   memset(temp_tx_buf,0x00,sizeof(temp_rx_buf));
   temp_tx_buf[0]=(reg & 0x7F);

   #ifdef DEBUG_SPI_BUFFER_INSIDE
   printf("bufp_len=%d \n",len);nrf_delay_ms(1);//app_uart_flush();
   printf("C00 temp_tx_buf=%2x\n",temp_tx_buf[0] );nrf_delay_ms(1);
   #endif

   for (uint8_t i = 0; i < len; i++) {
      temp_tx_buf[i+1] = bufp[i];
	  #ifdef DEBUG_SPI_BUFFER_INSIDE
      printf("C0%d temp_tx_buf=%2x\n",i+1,temp_tx_buf[i+1] );nrf_delay_ms(1);
	  #endif

   }
   int32_t ret;
   spi_xfer_done = false;
   ret=nrf_drv_spi_transfer(&spi, temp_tx_buf, 2, temp_rx_buf, len);
   
   APP_ERROR_CHECK(ret);	
   while(spi_xfer_done == false){};

  if(*spi_address==IMU_CS_M_PIN){nrf_gpio_pin_set(IMU_CS_M_PIN); }
  if(*spi_address==IMU_CS_AG_PIN){nrf_gpio_pin_set(IMU_CS_AG_PIN); }
  return 0;
}

 
void spi_init(void)
{        
    /* 初始化SPI0 */
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin   = SPI_SS_PIN;//nRF52832只能使用GPIO作为片选，所以这个单独定义了SPI CS管脚
    spi_config.miso_pin = SPI_MISO_PIN;
    spi_config.mosi_pin = SPI_MOSI_PIN;
    spi_config.sck_pin  = SPI_SCK_PIN;
    spi_config.frequency = NRF_DRV_SPI_FREQ_4M;
    nrf_gpio_cfg_output(IMU_CS_M_PIN); 
    nrf_gpio_cfg_output(IMU_CS_AG_PIN);
    nrf_gpio_cfg_output(IMU_POWER_PIN);
	
    nrf_gpio_pin_set(IMU_CS_M_PIN); 
    nrf_gpio_pin_set(IMU_CS_AG_PIN);
    nrf_gpio_pin_set(IMU_POWER_PIN);   
    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    nrf_gpio_pin_clear(IMU_POWER_PIN);  
    nrf_delay_ms(200);
    nrf_gpio_pin_set(IMU_POWER_PIN);  
    

}

void sensor_reset(void)       
{
   uint8_t temp_tx_buf[10];
   uint8_t temp_rx_buf[10];
   uint16_t len;
   memset(temp_tx_buf,0x00,sizeof(temp_tx_buf));
   memset(temp_tx_buf,0x00,sizeof(temp_rx_buf));
   
   printf("937\n");nrf_delay_ms(1);
   temp_tx_buf[0] = LSM9DS1_CTRL_REG8;
    temp_tx_buf[1] = 0x05; //bug in the datasheet
    //write8(XGTYPE, LSM9DS1_REGISTER_CTRL_REG8, 0x05);
    nrf_gpio_pin_clear(IMU_CS_AG_PIN); 
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, temp_tx_buf, 2, temp_rx_buf, len));
    nrf_gpio_pin_set(IMU_CS_AG_PIN); 
    printf("949\n");nrf_delay_ms(1);


    temp_tx_buf[0] = LSM9DS1_CTRL_REG3_M;
    temp_tx_buf[1] = 0b10000000; //bug in the datasheet
    nrf_gpio_pin_clear(IMU_CS_M_PIN); 
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, temp_tx_buf, 2, temp_rx_buf, len));
    nrf_gpio_pin_set(IMU_CS_M_PIN); 
    printf("1056\n");nrf_delay_ms(1);



}




void lsm9ds1_niklas_fifo_setup(void)
{
	uint32_t ret;
    uint8_t value;

	
	//LSM9DS1_CTRL_REG9          0x23U
	//lsm9ds1_fifo_stop_on_wtm_set(&dev_ctx_imu,  28);
			//LSM9DS1_FIFO_CTRL
        lsm9ds1_fifo_watermark_set(&dev_ctx_imu, 28);
        value=0;
	

        //LSM9DS1_FIFO_CTRL 0x2EU
		lsm9ds1_fifo_watermark_get(&dev_ctx_imu, &value);
        #ifdef DEBUG_FIFO_SIZE_INSIDE
        printf("wtm= %02x \n", value);  nrf_delay_ms(1);
        #endif
		
		
       //INT1_CTRL 0Ch     0b11101000 need to be reversed into below
	    lsm9ds1_pin_int1_route_t value_set;

        value_set.int1_drdy_xl=0;
        value_set.int1_drdy_g =0;
        value_set.int1_boot   =0;
        value_set.int1_fth    =1;
        value_set.int1_ovr    =0;
        value_set.int1_fss5   =1;
        value_set.int1_ig_xl  =1;
        value_set.int1_ig_g   =1;
	    lsm9ds1_pin_int1_route_set(&dev_ctx_imu, value_set); // need to check the LSM9DS1documentation
		
		

	
		//LSM9DS1_CTRL_REG9 0x23U
	    lsm9ds1_fifo_mode_set(&dev_ctx_imu, LSM9DS1_STREAM_TO_FIFO_MODE);

	
	


        value=(value_set.int1_drdy_xl<<7)+(value_set.int1_drdy_g <<6)+(value_set.int1_boot <<5)+ (value_set.int1_fth <<4)+(value_set.int1_ovr <<3)+(value_set.int1_fss5 <<2)+(value_set.int1_ig_xl  <<1)+value_set.int1_ig_g ;
        #ifdef DEBUG_FIFO_SIZE_INSIDE
        printf("i1_r_s= %02x\n", value);  nrf_delay_ms(1);
        #endif
 
        lsm9ds1_pin_int1_route_get(&dev_ctx_imu, &value_set); 


        //nrf_delay_ms(100);

        uint8_t unread_size;
        lsm9ds1_fifo_data_level_get(&dev_ctx_imu, &unread_size);
        #ifdef DEBUG_FIFO_SIZE_INSIDE
         printf("P00: %d", unread_size);nrf_delay_ms(1);
        #endif
		

}

uint8_t read_out_FIFO_float(void)
{
  uint32_t err_code;  
  uint8_t channel;
  uint8_t i=0;
  uint8_t k1=7;
  uint8_t k2=7;
  uint8_t unread_size;
  ble_tx_buffer_acc_len=0;
  ble_tx_buffer_ang_len=0;
  
  //header 0xAA 0xBB
  ble_tx_buffer_acc[0]=0xAA;
  ble_tx_buffer_acc[1]=0xBB;
  ble_tx_buffer_acc[2]=0x00;//reset into 0 first, laterly need to put in the length of the array/256 into it
  ble_tx_buffer_acc[3]=0x00;//reset into 0 first, laterly need to put in the length of the array%256 into it

  //Even package number for the acc 
  ble_tx_buffer_acc[4]=(uint8_t)(counter_flag/256);
  ble_tx_buffer_acc[5]=(uint8_t)(counter_flag%256); 

  ble_tx_buffer_acc[6]=0x00;//signal strength 
  counter_flag++;
  
  //header 0xAA 0xBB
  ble_tx_buffer_ang[0]=0xAA;
  ble_tx_buffer_ang[1]=0xBB;
  
  ble_tx_buffer_ang[2]=0x00;//reset into 0 first, laterly need to put in the length of the array/256 into it
  ble_tx_buffer_ang[3]=0x00;//reset into 0 first, laterly need to put in the length of the array%256 into it
  
  //Odd package number for the Ang
  ble_tx_buffer_ang[4]=(uint8_t)(counter_flag/256);
  ble_tx_buffer_ang[5]=(uint8_t)(counter_flag%256);

  ble_tx_buffer_ang[6]=0x00;//signal strength 
  counter_flag++;

  lsm9ds1_fifo_data_level_get(&dev_ctx_imu, &unread_size);
  #ifdef DEBUG_FIFO_SIZE_INSIDE
   printf("P1:%d\n", unread_size);nrf_delay_ms(1);
  #endif
  while ((unread_size&0b0011111)>0) //notice need to be changed 
  {
	    lsm9ds1_acceleration_raw_get(&dev_ctx_imu, data_raw_acceleration.u8bit);
        lsm9ds1_angular_rate_raw_get(&dev_ctx_imu, data_raw_angular_rate.u8bit);  
        lsm9ds1_fifo_data_level_get(&dev_ctx_imu, &unread_size);
		/*
		printf("Acc:%02x",  data_raw_acceleration.u8bit[0]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[1]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[2]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[3]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[4]);nrf_delay_ms(1);
		printf("    %02x\n",data_raw_acceleration.u8bit[5]);nrf_delay_ms(1);

		printf("Ang:%02x",  data_raw_angular_rate.u8bit[0]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[1]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[2]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[3]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[4]);nrf_delay_ms(1);
		printf("    %02x\n",data_raw_angular_rate.u8bit[5]);nrf_delay_ms(1);
		*/

		ble_tx_buffer_acc[k1]=data_raw_acceleration.u8bit[0];k1++;
		ble_tx_buffer_acc[k1]=data_raw_acceleration.u8bit[1];k1++;
		ble_tx_buffer_acc[k1]=data_raw_acceleration.u8bit[2];k1++;
		ble_tx_buffer_acc[k1]=data_raw_acceleration.u8bit[3];k1++;
		ble_tx_buffer_acc[k1]=data_raw_acceleration.u8bit[4];k1++;
		ble_tx_buffer_acc[k1]=data_raw_acceleration.u8bit[5];k1++;

		ble_tx_buffer_ang[k2]=data_raw_angular_rate.u8bit[0];k2++;
		ble_tx_buffer_ang[k2]=data_raw_angular_rate.u8bit[1];k2++;
		ble_tx_buffer_ang[k2]=data_raw_angular_rate.u8bit[2];k2++;
		ble_tx_buffer_ang[k2]=data_raw_angular_rate.u8bit[3];k2++;
		ble_tx_buffer_ang[k2]=data_raw_angular_rate.u8bit[4];k2++;
		ble_tx_buffer_ang[k2]=data_raw_angular_rate.u8bit[5];k2++;
        i++;
		
        //#ifdef DEBUG_FIFO_SIZE_INSIDE
        // printf(" P2:%d", i);nrf_delay_ms(1);
        //#endif
  }
  
  //should be refilled with crc
  ble_tx_buffer_acc[k1]=0xCC;k1++;
  ble_tx_buffer_acc[k1]=0xDD;k1++;
  
  ble_tx_buffer_ang[k2]=0xCC;k2++;
  ble_tx_buffer_ang[k2]=0xDD;k2++;
  
  ble_tx_buffer_acc[2]=k1/256;
  ble_tx_buffer_acc[3]=k1%256;
  
  ble_tx_buffer_ang[2]=k2/256;
  ble_tx_buffer_ang[3]=k2%256;

  ble_tx_buffer_acc_len=k1;
  ble_tx_buffer_ang_len=k2;
  if((status_connected==1)&&(status==9))
  {
    err_code =sd_ble_gap_rssi_get(m_conn_handle,&rssi_value,&channel);
    printf("0RSSI=%d\n",rssi_value);nrf_delay_ms(1);
    APP_ERROR_CHECK(err_code);
  }
  
  if(rssi_value<0)
  {
	  ble_tx_buffer_ang[6]=(unsigned char)(-rssi_value); 
	  ble_tx_buffer_acc[6]=(unsigned char)(-rssi_value); 
	  printf("1RSSI=-%d\n",ble_tx_buffer_acc[6]);nrf_delay_ms(1);
  }
  else
  {
	  ble_tx_buffer_ang[6]=(unsigned char)rssi_value;
	  ble_tx_buffer_acc[6]=(unsigned char)rssi_value;
	  printf("2RSSI=%d\n",ble_tx_buffer_acc[6]);nrf_delay_ms(1);
  }

  //#ifdef DEBUG_FIFO_SIZE_INSIDE
  // printf("P2:%d", i);nrf_delay_ms(1);
  //#endif
  #ifdef  WATCHDOG_ENABLE
  NRF_WDT->RR[0] = WDT_RR_RR_Reload;//reload watchdog
  #endif
  return i;
}

 
//void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
void in_pin_handler(void)
{
    //nrf_drv_gpiote_out_toggle(PIN_OUT);
    printf("INTC\n");nrf_delay_ms(1);
    uint8_t k=0;
    uint32_t err_code;  
    uint8_t channel;
    k=read_out_FIFO_float();
	
    bsp_board_led_invert(BSP_BOARD_LED_2);
	
    #ifdef DEBUG_FIFO_SIZE_INSIDE
	 printf("P3:%d\n", k);nrf_delay_ms(1);
	 printf("s_connected=%d\n",status_connected);nrf_delay_ms(1);
    #endif
	
    #ifdef DEBUG_BLE_SEND_DEBUG
  	 printf("ble_tx_buffer_acc_len=%d\n",ble_tx_buffer_acc_len);nrf_delay_ms(1);
  	 printf("ble_tx_buffer_ang_len=%d\n",ble_tx_buffer_ang_len);nrf_delay_ms(1);
  	 printf("BLE_NUS_MAX_DATA_LEN=%d\n",BLE_NUS_MAX_DATA_LEN);nrf_delay_ms(1);
    #endif
	
	//if((status_connected==1)&&(status==9)){niklas_ble_send_handler();}
	if((status_connected==1)&&(status==9))
        {
          
          #ifdef LONG_RANGE_HIGH_SPEED_BLE_STREAMING_SLOW
            ble_tx_buffer_acc_len=5;
            ble_tx_buffer_ang_len=5;
          #endif
          niklas_ble_send_array_handler();


          
          
          //reference https://www.jianshu.com/p/c81c576bbdf5
          /*
		  err_code =sd_ble_gap_rssi_get(m_conn_handle,&rssi_value,&channel);
          printf("RSSI=%d\n",rssi_value);nrf_delay_ms(1);
          APP_ERROR_CHECK(err_code);
		  */

        
        }

}

static void interrupt_pin_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    //nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);

    //err_code = nrf_drv_gpiote_out_init(PIN_OUT, &out_config);
    //APP_ERROR_CHECK(err_code);
                                          //GPIOTE_CONFIG_IN_SENSE_LOTOHI  //GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI
    nrf_drv_gpiote_in_config_t in_config =GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);// GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
    in_config.pull = NRF_GPIO_PIN_PULLDOWN;//NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(PIN_INTERRUPT, &in_config, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(PIN_INTERRUPT, true);
     printf("pin_init");nrf_delay_ms(1);
     if(nrf_gpio_pin_read(PIN_INTERRUPT))
			{ 
			 printf("1321");
			 //in_pin_handler();
			}
                        else
                        {
                         printf("1326");
                        }

}



uint8_t LSM9DS1_looking(void)
{
    uint8_t find_flag=0;
    printf("\r\n SPI started.\r\n");nrf_delay_ms(1);
    //spi_init();
    sensor_reset();

    //Initialize inertial sensors (IMU) driver interface 
    dev_ctx_mag.write_reg = platform_write;
    dev_ctx_mag.read_reg = platform_read;
    dev_ctx_mag.handle = (void*)&spi_add_mag;

    // Initialize magnetic sensors driver interface 
    dev_ctx_imu.write_reg = platform_write;
    dev_ctx_imu.read_reg = platform_read;
    dev_ctx_imu.handle = (void*)&spi_add_imu;

    // Check device ID 
    lsm9ds1_dev_id_get(&dev_ctx_mag, &dev_ctx_imu, &whoamI);
	//app_uart_flush();
	nrf_delay_ms(1);
        printf("who imu= %X\n",whoamI.imu);nrf_delay_ms(1);//nrf_delay_ms(1);//app_uart_flush();
	printf("who mag= %X\n",whoamI.mag);nrf_delay_ms(1);//nrf_delay_ms(1);//app_uart_flush();

    if (whoamI.imu != LSM9DS1_IMU_ID || whoamI.mag != LSM9DS1_MAG_ID){
    
        //manage here device not found 
        //NRF_LOG_INFO("\r\nCannot find the LSM9DS1.********\r\n");
        //NRF_LOG_FLUSH();
        printf("\r\nCannot find the LSM9DS1.********\r\n");nrf_delay_ms(1);
        lsm9ds1_dev_id_get(&dev_ctx_mag, &dev_ctx_imu, &whoamI);
      find_flag=0;
    }
	else
	{
		find_flag=1;
	}
    printf("Who am I register [IMU]: 0x%x [MAG]: 0x%x \r\n\n", whoamI.imu, whoamI.mag);  nrf_delay_ms(1);//app_uart_flush();

     printf("                 L0 \r\n");nrf_delay_ms(1);
     //Restore default configuration 
    lsm9ds1_dev_reset_set(&dev_ctx_mag, &dev_ctx_imu, PROPERTY_ENABLE);
    return find_flag;
}


void LSM9DS1_start(void)
{
	
     //Restore default configuration 
    lsm9ds1_dev_reset_set(&dev_ctx_mag, &dev_ctx_imu, PROPERTY_ENABLE);


     printf("                 L1 \r\n");nrf_delay_ms(1);
     do {
      lsm9ds1_dev_reset_get(&dev_ctx_mag, &dev_ctx_imu, &rst);
      printf("rst =:0x%x \r\n", rst);  nrf_delay_ms(1);
    } while (rst);

     printf("                 L2 \r\n");nrf_delay_ms(1);

    lsm9ds1_niklas_fifo_setup();
    
    //Enable Block Data Update 
    lsm9ds1_block_data_update_set(&dev_ctx_mag, &dev_ctx_imu, PROPERTY_ENABLE);
     printf("                 L3 \r\n");nrf_delay_ms(1);

    //Set full scale 
    lsm9ds1_xl_full_scale_set(&dev_ctx_imu, LSM9DS1_4g);
    lsm9ds1_gy_full_scale_set(&dev_ctx_imu, LSM9DS1_2000dps);
    lsm9ds1_mag_full_scale_set(&dev_ctx_mag, LSM9DS1_16Ga);
    printf("                 L4 \r\n");nrf_delay_ms(1);

    //Configure filtering chain - See datasheet for filtering chain details 
    //Accelerometer filtering chain 
    lsm9ds1_xl_filter_aalias_bandwidth_set(&dev_ctx_imu, LSM9DS1_AUTO);
    lsm9ds1_xl_filter_lp_bandwidth_set(&dev_ctx_imu, LSM9DS1_LP_ODR_DIV_50);
    lsm9ds1_xl_filter_out_path_set(&dev_ctx_imu, LSM9DS1_LP_OUT);
    printf("                 L5 \r\n");nrf_delay_ms(1);
    //Gyroscope filtering chain 
    lsm9ds1_gy_filter_lp_bandwidth_set(&dev_ctx_imu, LSM9DS1_LP_ULTRA_LIGHT);//LSM9DS1_LP_STRONG);//
    lsm9ds1_gy_filter_hp_bandwidth_set(&dev_ctx_imu, LSM9DS1_HP_MEDIUM);
    lsm9ds1_gy_filter_out_path_set(&dev_ctx_imu, LSM9DS1_LPF1_HPF_LPF2_OUT);
    printf("                 L6 \r\n");nrf_delay_ms(1);

    //Set Output Data Rate / Power mode 
    lsm9ds1_imu_data_rate_set(&dev_ctx_imu,LSM9DS1_IMU_238Hz);// LSM9DS1_IMU_14Hz9);//LSM9DS1_IMU_59Hz5);
	//lsm9ds1_imu_data_rate_set(&dev_ctx_imu, LSM9DS1_IMU_952Hz);
    printf("                 L7 \r\n");nrf_delay_ms(3);
        lsm9ds1_mag_data_rate_set(&dev_ctx_mag, LSM9DS1_MAG_UHP_10Hz);
      //lsm9ds1_mag_data_rate_set(&dev_ctx_mag, LSM9DS1_MAG_LP_1000Hz);
    printf("                 L8 \r\n");nrf_delay_ms(3);
   // interrupt_pin_init();

}


/**@brief Application main function.
 */
int main(void)
{


    #ifdef  WATCHDOG_ENABLE
    //Configure WDT.
    //reference https://devzone.nordicsemi.com/f/nordic-q-a/53904/nrf52840-watchdog-for-arduino-nano-33-ble-sense
    NRF_WDT->CONFIG         = 0x01;     // Configure WDT to run when CPU is asleep
    //NRF_WDT->CRV            = 3932159;  // Timeout set to 120 seconds, timeout[s] = (CRV-1)/32768
    //NRF_WDT->CRV              = 983041;  // Timeout set to 30 seconds, timeout[s] = (CRV-1)/32768
    //NRF_WDT->CRV              = 327681;  // Timeout set to 10 seconds, timeout[s] = (CRV-1)/32768
    NRF_WDT->CRV              = 98305;  // Timeout set to 3 seconds, timeout[s] = (CRV-1)/32768
    //NRF_WDT->CRV              = 32769;  // Timeout set to 1 seconds, timeout[s] = (CRV-1)/32768
    NRF_WDT->RREN           = 0x01;     // Enable the RR[0] reload register
    NRF_WDT->TASKS_START    = 1;        // Start WDT
    #endif

    bool erase_bonds;
    uint8_t find_flag=0;
        
    // Initialize.
    uart_init();
    log_init();
    timers_init();
    //buttons_leds_init(&erase_bonds);

    printf("\n\n\nNiklas ex start.\n");nrf_delay_ms(1);
    bsp_board_init(BSP_INIT_LEDS);





    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

    // Start execution.
    printf("UART started.\r\n");nrf_delay_ms(1);
    //NRF_LOG_INFO("Debug logging for UART over RTT started.");
    advertising_start();
    printf("adv started.\r\n");nrf_delay_ms(1);
    spi_init();
    printf("spi started.\r\n");nrf_delay_ms(1);

    while(find_flag!=1)
    {
    	find_flag=LSM9DS1_looking();
    	printf("find_flag=%d\n",find_flag);nrf_delay_ms(1);
    }
        
    LSM9DS1_start();
    interrupt_pin_init();
	

          
    /*
    while (true)
    {
      //Read device status register 
      lsm9ds1_dev_status_get(&dev_ctx_mag, &dev_ctx_imu, &reg);

      if ( reg.status_imu.xlda && reg.status_imu.gda ){
        //Read imu data
        memset(data_raw_acceleration.u8bit, 0x00, 3 * sizeof(int16_t));
        memset(data_raw_angular_rate.u8bit, 0x00, 3 * sizeof(int16_t));

        lsm9ds1_acceleration_raw_get(&dev_ctx_imu, data_raw_acceleration.u8bit);
        lsm9ds1_angular_rate_raw_get(&dev_ctx_imu, data_raw_angular_rate.u8bit);

        acceleration_mg[0] = lsm9ds1_from_fs4g_to_mg(data_raw_acceleration.i16bit[0]);
        acceleration_mg[1] = lsm9ds1_from_fs4g_to_mg(data_raw_acceleration.i16bit[1]);
        acceleration_mg[2] = lsm9ds1_from_fs4g_to_mg(data_raw_acceleration.i16bit[2]);

        angular_rate_mdps[0] = lsm9ds1_from_fs2000dps_to_mdps(data_raw_angular_rate.i16bit[0]);
        angular_rate_mdps[1] = lsm9ds1_from_fs2000dps_to_mdps(data_raw_angular_rate.i16bit[1]);
        angular_rate_mdps[2] = lsm9ds1_from_fs2000dps_to_mdps(data_raw_angular_rate.i16bit[2]);
		
		printf("Acc:%02x",  data_raw_acceleration.u8bit[0]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[1]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[2]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[3]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_acceleration.u8bit[4]);nrf_delay_ms(1);
		printf("    %02x\n",data_raw_acceleration.u8bit[5]);nrf_delay_ms(1);
		
		printf("Acc:%04x",  data_raw_acceleration.i16bit[0]);nrf_delay_ms(1);
		printf("    %04x",  data_raw_acceleration.i16bit[1]);nrf_delay_ms(1);
		printf("    %04x\n",data_raw_acceleration.i16bit[2]);nrf_delay_ms(1);
		
		//printf("flo:%4.2f",  0.033*0.51);nrf_delay_ms(1);
		//printf("    %4.2f",  0.033*0.52);nrf_delay_ms(1);
		//printf("    %4.2f\n",0.033*0.53);nrf_delay_ms(1);
	
		printf("Ang:%02x",  data_raw_angular_rate.u8bit[0]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[1]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[2]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[3]);nrf_delay_ms(1);
		printf("    %02x",  data_raw_angular_rate.u8bit[4]);nrf_delay_ms(1);
		printf("    %02x\n",data_raw_angular_rate.u8bit[5]);nrf_delay_ms(1);
		
		printf("Ang:%04x",  data_raw_angular_rate.i16bit[0]);nrf_delay_ms(1);
		printf("    %04x",  data_raw_angular_rate.i16bit[1]);nrf_delay_ms(1);
		printf("    %04x\n",data_raw_angular_rate.i16bit[2]);nrf_delay_ms(1);		
		

        sprintf((char*)tx_buffer, "IMU - [mg]:%4.2f\t%4.2f\t%4.2f\t\n[mdps]:%4.2f\t%4.2f\t%4.2f\r\n",
                acceleration_mg[0], acceleration_mg[1], acceleration_mg[2],
                angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);
	    nrf_delay_ms(1);
        //sprintf((char *)tx_buffer, "Moj IMU - mg[0]: %4.2f \r\n", acceleration_mg[0]);

        //printf("            IMU - [mg]: %4.2f",acceleration_mg[0]);nrf_delay_ms(1);
		//printf("            IMU - [mg]: %4.2f",acceleration_mg[0]);nrf_delay_ms(1);
		
		nrf_delay_ms(1);nrf_delay_ms(1);nrf_delay_ms(1);
        printf(tx_buffer);
        //NRF_LOG_FLUSH();
      }

      
	  if ( reg.status_mag.zyxda ){
        //Read magnetometer data 
        memset(data_raw_magnetic_field.u8bit, 0x00, 3 * sizeof(int16_t));

        lsm9ds1_magnetic_raw_get(&dev_ctx_mag, data_raw_magnetic_field.u8bit);

        magnetic_field_mgauss[0] = lsm9ds1_from_fs16gauss_to_mG(data_raw_magnetic_field.i16bit[0]);
        magnetic_field_mgauss[1] = lsm9ds1_from_fs16gauss_to_mG(data_raw_magnetic_field.i16bit[1]);
        magnetic_field_mgauss[2] = lsm9ds1_from_fs16gauss_to_mG(data_raw_magnetic_field.i16bit[2]);

        sprintf(tx_buffer, "MAG - [mG]:%4.2f\t%4.2f\t%4.2f\r\n",
                magnetic_field_mgauss[0], magnetic_field_mgauss[1], magnetic_field_mgauss[2]);nrf_delay_ms(1);
        printf(tx_buffer);nrf_delay_ms(1);nrf_delay_ms(1);nrf_delay_ms(1);
        //NRF_LOG_INFO(tx_buffer);
          //NRF_LOG_FLUSH();
      }
	 
	  
	  nrf_delay_ms(500);
    }
   */




    uint8_t counter_flag=0;
    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
        //APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
         //bsp_board_led_invert(BSP_BOARD_LED_2);
         
         #ifdef LONG_RANGE_HIGH_SPEED
         if(status_connected==1)
         {
            nrf_delay_ms(1000);
            /*
            if(nrf_gpio_pin_read(PIN_INTERRUPT))
	    { 
	       printf("In BB:\n");nrf_delay_ms(1);
               
               counter_flag=counter_flag+1;
               if(counter_flag>1)
               {
                  LSM9DS1_start();
                  interrupt_pin_init();
               }
            }
            //LSM9DS1_looking();
            */

            
            ble_tx_buffer_acc_len=10;//256;
            ble_tx_buffer_ang_len=10;//256;
            niklas_ble_send_array_handler();
            printf("BLEsend:\n");nrf_delay_ms(1);
            
         }
         else
         {
          counter_flag=0;
         }

         
         #endif

 

    }
}