/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 */

/** @file
 * @defgroup uart_example_main main.c
 * @{
 * @ingroup uart_example
 * @brief UART Example Application main file.
 *
 * This file contains the source code for a sample application using UART.
 * 
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_error.h"
#include "app_uart.h"
#include "bsp.h"
#include "nrf.h"
#include "nrf_delay.h"

#include <string.h>
#include "app_error.h"
#include "app_util_platform.h"
#include "boards.h"
#include "nrf_delay.h"
#include "nrf_drv_spi.h"
#include "nrf_gpio.h"
#define NRF_LOG_MODULE_NAME "APP"
#include "nrf_drv_timer.h"
#include "nrf_log.h"

//parameter for getting index of data array
int p = 0;

#define US_TSET_PIN 17          // CHANGED THIS to see the LED toggle
const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(4);

#define SPI_INSTANCE 1 /**< SPI instance index. */
#ifndef SPI_SS_PIN
#define SPI_SS_PIN 29
#endif

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. */

void spi_event_handler(nrf_drv_spi_evt_t const* p_event)
{
    spi_xfer_done = true;
}

void spi_init(void)
{
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG(1);
    spi_config.ss_pin               = SPI_SS_PIN;
    spi_config.miso_pin             = SPI1_CONFIG_MISO_PIN;
    spi_config.mosi_pin             = SPI1_CONFIG_MOSI_PIN;
    spi_config.sck_pin              = SPI1_CONFIG_SCK_PIN;
    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));
}

//#define ENABLE_LOOPBACK_TEST  /**< if defined, then this example will be a loopback test, which means that TX should be connected to RX to get data loopback. */

#define MAX_TEST_DATA_BYTES (15U) /**< max number of test bytes to be used for tx and rx. */
#define UART_TX_BUF_SIZE 256      /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256      /**< UART RX buffer size. */

void uart_error_handle(app_uart_evt_t* p_event)
{
    if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_communication);
    }
    else if (p_event->evt_type == APP_UART_FIFO_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_code);
    }
}

void uart_init()
{
    uint32_t                     err_code;
    const app_uart_comm_params_t comm_params =
        {
            RX_PIN_NUMBER,
            TX_PIN_NUMBER,
            RTS_PIN_NUMBER,
            CTS_PIN_NUMBER,
            APP_UART_FLOW_CONTROL_DISABLED,
            false,
            UART_BAUDRATE_BAUDRATE_Baud115200};

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_error_handle,
                       APP_IRQ_PRIORITY_LOW,
                       err_code);

    APP_ERROR_CHECK(err_code);
}

#ifdef ENABLE_LOOPBACK_TEST
/** @brief Function for setting the @ref ERROR_PIN high, and then enter an infinite loop.
 */
static void show_error(void)
{
    LEDS_ON(LEDS_MASK);
    while (true)
    {
        // Do nothing.
    }
}

/** @brief Function for testing UART loop back. 
 *  @details Transmitts one character at a time to check if the data received from the loopback is same as the transmitted data.
 *  @note  @ref TX_PIN_NUMBER must be connected to @ref RX_PIN_NUMBER)
 */
/*static void uart_loopback_test()      // Not used
{
    uint8_t * tx_data = (uint8_t *)("\n\rLOOPBACK_TEST\n\r");
    uint8_t   rx_data;

    // Start sending one byte and see if you get the same
    for (uint32_t i = 0; i < MAX_TEST_DATA_BYTES; i++)
    {
        uint32_t err_code;
        while(app_uart_put(tx_data[i]) != NRF_SUCCESS);

        nrf_delay_ms(10);
        err_code = app_uart_get(&rx_data);

        if ((rx_data != tx_data[i]) || (err_code != NRF_SUCCESS))
        {
            show_error();
        }
    }
    return;
}*/

#endif
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            NRF_TIMER4->EVENTS_COMPARE[0] = 0;
            nrf_gpio_pin_toggle(US_TSET_PIN);
            break;

        default:
            //Do nothing.
            break;
    }
}
void timer_init()
{
    uint32_t err_code = NRF_SUCCESS;
    nrf_gpio_cfg_output(US_TSET_PIN);

    nrf_gpio_pin_set(US_TSET_PIN);

    //Configure all leds on board.
    LEDS_CONFIGURE(LEDS_MASK);
    LEDS_OFF(LEDS_MASK);

    //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_config;
    timer_config.bit_width          = NRF_TIMER_BIT_WIDTH_32;       // had to set this because if timer_config is NULL, the defaults from nrf_drv_config.h is used, which sets bit width to 16.
    timer_config.frequency          = NRF_TIMER_FREQ_16MHz;         // the rest of timer_config settings are equivalent to default settings of TIMER4 in nrf_drv_config.h
    timer_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;
    timer_config.mode               = NRF_TIMER_MODE_TIMER;
    timer_config.p_context          = NULL;
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_config/*NULL*/, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);
    uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ticks;
    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);

    nrf_drv_timer_extended_compare(
        &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_LED);

/*    while (1)             //REMOVE THIS. gets stuck in a while loop.
    {
        __WFI();
    }*/
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    timer_init();
    uart_init();

    while (1)
    {
        uint8_t cr;
        while (app_uart_get(&cr) != NRF_SUCCESS);
        while (app_uart_put(cr) != NRF_SUCCESS);
    }
}

/** @} */
