#include <stdint.h>
#include <stdbool.h>
#include "nrf.h"
#include "app_error.h"
#include "nrf_gpio.h"
#include "nrf_sdh.h"
#include "boards.h"
#include "nrf_sdh_soc.h"

void nrf_evt_signal_handler(uint32_t evt_id,void * p_context);
NRF_SDH_SOC_OBSERVER(m_sys_radio_signal_obs, 0, nrf_evt_signal_handler, NULL);
/**Constants for timeslot API
*/
static nrf_radio_request_t  m_timeslot_request;
static uint32_t             m_slot_length;

static nrf_radio_signal_callback_return_param_t signal_callback_return_param;

#define TIMESLOT_TIMEOUT 100000
static uint32_t distance_increased =0;
/**@brief Request next timeslot event in earliest configuration
 */
uint32_t request_next_event_earliest(void)//首次调用使用这个函数，
{
	 uint32_t timeout = 120*1000;//timeout 120ms
    m_slot_length                                  = 100000;  //6ms，最长时间为128ms
	
    m_timeslot_request.request_type                = NRF_RADIO_REQ_TYPE_EARLIEST;
    m_timeslot_request.params.earliest.hfclk       = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
    m_timeslot_request.params.earliest.priority    = NRF_RADIO_PRIORITY_HIGH;
    m_timeslot_request.params.earliest.length_us   = m_slot_length;
    m_timeslot_request.params.earliest.timeout_us  = timeout;//超时时间设置为120ms
	
	 printf("first request earliest length_us=%d,timeout=%d\r\n",m_slot_length,timeout);
    return sd_radio_request(&m_timeslot_request);
}


/**@brief Configure next timeslot event in earliest configuration
 */
void configure_next_event_earliest(void)//再次配置m_timeslot_request参数
{
    m_slot_length                                  = 100000;
    m_timeslot_request.request_type                = NRF_RADIO_REQ_TYPE_EARLIEST;
    m_timeslot_request.params.earliest.hfclk       = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
    m_timeslot_request.params.earliest.priority    = NRF_RADIO_PRIORITY_HIGH;
    m_timeslot_request.params.earliest.length_us   = m_slot_length;
    m_timeslot_request.params.earliest.timeout_us  = 120*1000;
}

/**@brief Timeslot signal handler
 */
void nrf_evt_signal_handler(uint32_t evt_id,void * p_context)
{
    uint32_t err_code;
    
    switch (evt_id)
    {
        case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
			  printf("NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN\r\n");
            //No implementation needed
            break;
        case NRF_EVT_RADIO_SESSION_IDLE:
			  printf("NRF_EVT_RADIO_SESSION_IDLE\r\n");
            //No implementation needed
            break;
        case NRF_EVT_RADIO_SESSION_CLOSED:
			  printf("NRF_EVT_RADIO_SESSION_CLOSED\r\n");
            //No implementation needed, session ended
                break;
        case NRF_EVT_RADIO_BLOCKED:
			  printf("NRF_EVT_RADIO_BLOCKED\r\n");
            //Fall through
        case NRF_EVT_RADIO_CANCELED:
				printf("NRF_EVT_RADIO_CANCELED %d\r\n",distance_increased+1);		
				request_next_event_earliest();	  
            APP_ERROR_CHECK(err_code);
            break;
        default:
            break;
    }
}


/**@brief Timeslot event handler
 */
nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type)
{
    switch(signal_type)
    {
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
			  printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_START\r\n");
            NRF_TIMER0->TASKS_STOP          = 1;
            NRF_TIMER0->TASKS_CLEAR         = 1;
            NRF_TIMER0->MODE                = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos);
            NRF_TIMER0->EVENTS_COMPARE[0]   = 0;     
            
            //Start of the timeslot - set up timer interrupt
            signal_callback_return_param.params.request.p_next = NULL;
            signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
            distance_increased=0;
            NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
            NRF_TIMER0->CC[0] = m_slot_length - 500;   //单位是us  5.5ms的时候，产生NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0信号
				NRF_TIMER0->TASKS_START         = 1;
            NVIC_EnableIRQ(TIMER0_IRQn);   
            
				nrf_gpio_pin_set (19);   //示波器高电平
				break;

        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
			  printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO\r\n");
            signal_callback_return_param.params.request.p_next = NULL;
            signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
            break;

        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
			  printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0\r\n");
            //Timer interrupt - do graceful shutdown - schedule next timeslot
				nrf_gpio_pin_clear (19);   //示波器低电平
//            configure_next_event_normal();
				configure_next_event_earliest();
            NRF_TIMER0->TASKS_STOP  = 1;
            NRF_TIMER0->EVENTS_COMPARE[0] = 0;
				NRF_TIMER0->INTENCLR =TIMER_INTENSET_COMPARE2_Msk|TIMER_INTENSET_COMPARE1_Msk;

            signal_callback_return_param.params.request.p_next = &m_timeslot_request;  //放入下一个请求
            signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
            break;
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
			  printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED\r\n");
            //No implementation needed
            break;
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
            //Try scheduling a new timeslot
            configure_next_event_earliest();
            signal_callback_return_param.params.request.p_next = &m_timeslot_request;
            signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
            break;
        default:
            //No implementation needed
            break;
    }
    return (&signal_callback_return_param);
}


/**@brief Function for initializing the timeslot API.
*初始化timeslot
 */
uint32_t timeslot_sd_init(void)
{
    uint32_t err_code;
    
    err_code = sd_radio_session_open(radio_callback);//打开timeslot会话
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    
    err_code = request_next_event_earliest();
    if (err_code != NRF_SUCCESS)//if failed close session，如果打开绘画打开失败，则关闭会话。
    {
        (void)sd_radio_session_close();
        return err_code;
    }
    return NRF_SUCCESS;
}

