/**
 * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA
 *
 */

#include <stdint.h>
#include "nordic_common.h"
#include "nrf.h"
#include "app_timer.h"
#include "app_button.h"
////////////////////////////


#include "nrfx_spim.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 "nrf_drv_clock.h"

#define NRFX_SPIM_SCK_PIN  3
#define NRFX_SPIM_MOSI_PIN 4
#define NRFX_SPIM_MISO_PIN 28
#define NRFX_SPIM_SS_PIN   29
#define NRFX_SPIM_DCX_PIN  30

#define BUTTON_DETECTION_DELAY          APP_TIMER_TICKS(100)    

    // APP_SPIS_CS_PIN 31
    // APP_SPIS_MISO_PIN 30
    // APP_SPIS_MOSI_PIN 29
    // APP_SPIS_SCK_PIN 26

#define SPI_INSTANCE  3                                           /**< SPI instance index. */
static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */

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

#define TEST_STRING "Nordic123456789012345678901234567890"
static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];  /**< RX buffer. */
static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
    spi_xfer_done = true;
    NRF_LOG_INFO("Transfer completed.");
    if (m_rx_buf[0] != 0)
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
    }
}

/////////////////////////////////////
static void log_init(void)
{
    ret_code_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();
}

static void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    ret_code_t err_code;
    switch (pin_no)
    {
        case BSP_BUTTON_0:
            NRF_LOG_INFO("Send button state change.");
            break;
        case BSP_BUTTON_1:
            if (button_action == APP_BUTTON_PUSH)
              {
                NRF_LOG_INFO("BSP_BUTTON_2 clicked - start SPI TRX Timer");
                bsp_board_led_invert(BSP_BOARD_LED_0);
              }
            break;
        case BSP_BUTTON_2:
            if (button_action == APP_BUTTON_PUSH)
              {
                NRF_LOG_INFO("BSP_BUTTON_3 clicked - TOGGLE LED 1");
                bsp_board_led_invert(BSP_BOARD_LED_1);
              }
            break;

        default:
            APP_ERROR_HANDLER(pin_no);
            break;
    }
}

static void leds_init(void)
{
    bsp_board_init(BSP_INIT_LEDS);
}

static void timers_init(void)
{
    // Initialize timer module, making it use the scheduler
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
}


static void buttons_init(void)
{
    ret_code_t err_code;

    //The array must be static because a pointer to it will be saved in the button handler module.
    static app_button_cfg_t buttons[] =
    {
        {BSP_BUTTON_0, false, BUTTON_PULL, button_event_handler},
        {BSP_BUTTON_1, false, BUTTON_PULL, button_event_handler},
        {BSP_BUTTON_2, false, BUTTON_PULL, button_event_handler}
    };

    err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                               BUTTON_DETECTION_DELAY);
    APP_ERROR_CHECK(err_code);
    
}

////////////////////////////////////




static void lfclk_request(void)
{

    ret_code_t  err_code    =   nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);
}

int main(void)
{
    lfclk_request();
    log_init();
    leds_init();
    timers_init();
    buttons_init();
    



    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);

    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.frequency      = NRF_SPIM_FREQ_1M;
    spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
    spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
    spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
    spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
    //spi_config.dcx_pin        = NRFX_SPIM_DCX_PIN;
    spi_config.dcx_pin        = NRFX_SPIM_PIN_NOT_USED;
    spi_config.use_hw_ss      = true;
    spi_config.ss_active_high = false;
    APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));

    NRF_LOG_INFO("NRFX SPIM example started.");

    app_button_enable();
    while (1)
    {
        // Reset rx buffer and transfer done flag
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;

        //APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));
        APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));

        while (!spi_xfer_done)
        {
            __WFE();
        }

        NRF_LOG_FLUSH();

        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(500);
    }
}