/**
******************************************************************************************************************************************************************************************
*@file                       user_timer.c
*@author         
*@data                       
*@version                    v1.0
*@par Copyright(c):
*
*@par History:
*     version:author,date,desc
*     v1.0   :create this file
*
*******************************************************************************************************************************************************************************************
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "cpu.h"
#include "user_timer.h"
#include "cpu_deepsleep.h"
#include "app_trace.h"

/// 
#define TIMER_CONTROL_REG_TIMER_ENABLE_Pos                              (0)
#define TIMER_CONTROL_REG_TIMER_ENABLE_Mask                             (0x01U<<TIMER_CONTROL_REG_TIMER_ENABLE_Pos) 

/// 
#define TIMER_CONTROL_REG_TIMER_MODE_Pos                                (1)
#define TIMER_CONTROL_REG_TIMER_MODE_Mask                               (0x01U<<TIMER_CONTROL_REG_TIMER_MODE_Pos) //1 fixed, timed interrupt;0 

/// 
#define TIMER_CONTROL_REG_TIMER_INTERRUPT_MASK_Pos                      (2)
#define TIMER_CONTROL_REG_TIMER_INTERRUPT_MASK_Mask                     (0x01U<<TIMER_CONTROL_REG_TIMER_INTERRUPT_MASK_Pos) 

/// 
#define TIMER_INT_STATUS_INTSTATUS_Pos                                  (0)
#define TIMER_INT_STATUS_INTSTATUS_Mask                                 (0x01U<<TIMER_INT_STATUS_INTSTATUS_Pos) 

/// globle timers raw interrupt status
#define TIMER0_RAW_INT_STATUS_Pos                                        (0)
#define TIMER0_RAW_INT_STATUS_Mask                                       (0x01U<<TIMER0_RAW_INT_STATUS_Pos)
#define TIMER1_RAW_INT_STATUS_Pos                                        (1)
#define TIMER1_RAW_INT_STATUS_Mask                                       (0x01U<<TIMER1_RAW_INT_STATUS_Pos)

typedef struct
{
    timer_event_cbk_t timer_cbk[IDX_TIMER_NUM];
}timer_env_t;

/// timer environment
timer_env_t timer_env;

/*
* brief: config open or close interrupt.
* param[0]: timer type.
* param[1]: timer interrupt config state.
*/
static void timer_irr_config(timer_type_def* timerx,functional_state_t new_state)
{
    if(new_state != DISABLE)
        timerx->ControlReg &= ~TIMER_CONTROL_REG_TIMER_INTERRUPT_MASK_Mask;
    else
        timerx->ControlReg |= TIMER_CONTROL_REG_TIMER_INTERRUPT_MASK_Mask;
}

/*
* brief: get timer current conunt value.
* param[0]: timer type.
* return  : current count vlaue.
*/
uint32_t timer_get_currentcount(timer_type_def *timer_idx)
{
    return timer_idx->CurrentValue;
}


/*
* brief: initialize timer.
*/
void user_timer_init(void)
{
    memset(&timer_env, 0, sizeof(timer_env_t));
}

/*
* brief: start or stop a timer.
* param[0] : timer index.
* param[1] : TIMER_START/TIMER_START.
*/
void timer_enable_ctrl_cmd(timer_type_def *timerx, timer_cmd_t new_state)
{
    
    if(new_state != TIMER_STOP)
    {
        /// TIMER will start work.
        timerx->ControlReg |= TIMER_CONTROL_REG_TIMER_ENABLE_Mask;
        
    }
    else
    {
        /// TIMER will stop work.
        timerx->ControlReg &= ~TIMER_CONTROL_REG_TIMER_ENABLE_Mask;
        
    }

}

/*
* brief: config a timer.
* param[0]: timer type.
* param[1]: timer config paramter.
* param[2]: timer callbcak.
*/
void timer_config(timer_type_def *timerx, timer_config_t *p_config, timer_event_cbk_t cbk)
{
    /// first stop timer.
    timer_enable_ctrl_cmd(timerx, TIMER_STOP);
    
   if(p_config ==NULL || cbk == NULL)
        return ;

    timerx->LoadCount = p_config->timer_param.timer_period;
    timerx->ControlReg |= TIMER_CONTROL_REG_TIMER_MODE_Mask;
    timer_env.timer_cbk[p_config->timer_idx] = cbk;
    timer_irr_config(timerx,ENABLE);
}
/*
* brief: clear interrupt state RC.
* param[0]: timer type.
*/
void timer_clear_interrupt(timer_type_def *timerx)
{
    uint32_t clr = timerx->EOI;
}

/*
* brief: determine if the timer is working.
* param[0]: timer type.
* return  : true:timer is working. or not.
*/
bool timer_is_working(timer_type_def *timerx)
{
    return (timerx->ControlReg & TIMER_CONTROL_REG_TIMER_ENABLE_Mask);
}

/*
* brief: distribute interrupt handle.
* param[0]: timer type.
* param[1]: itmer index.
*/
void timer_x_isr(timer_type_def *timerx,timer_idx_t timer_idx)
{
    timer_clear_interrupt(timerx);
    if(timer_env.timer_cbk[timer_idx] != NULL)
        timer_env.timer_cbk[timer_idx](timer_idx);
}

/*
* brief: timer interrupt hanle from xx.s file.
*/


void TIMER0_IRQHandler(void)
{
    timer_x_isr(TIMER0, IDX_TIMER0);
    timer_clear_it_pending_bit(TIMER0);
}

void TIMER1_IRQHandler(void)
{
    timer_x_isr(TIMER1, IDX_TIMER1);
}

void TIMER2_IRQHandler(void)
{
    timer_x_isr(TIMER2, IDX_TIMER2);
}

void TIMER3_IRQHandler(void)
{
    timer_x_isr(TIMER3, IDX_TIMER3);
}

/*
* brief: start or stop a timer.
* param[0] : timer device index.
* param[1] : TIMER_START/TIMER_START.
*/
void timer_enable_ctrl_cmd_ex(ws_dev timer_dev, timer_cmd_t new_state)
{
	timer_type_def *timerx;
	cpu_prevent_sleep_t msk;
	switch(timer_dev){
		case ws_timer0:
			timerx	=	TIMER0;
			msk 	= 	TIMER0_ONGOING;
			break;
		case ws_timer1:
			timerx	=	TIMER1;
			msk 	= 	TIMER1_ONGOING;
			break;
		case ws_timer2:
			timerx	=	TIMER2;
			msk 	= 	TIMER2_ONGOING;
			break;
		case ws_timer3:
			timerx	=	TIMER3;
			msk 	= 	TIMER3_ONGOING;
			break;
		default:
			return;
	}
	
    if(new_state != TIMER_STOP)
    {
        /// TIMER will start work.
		cpu_prevent_sleep_set(msk);
        timerx->ControlReg |= TIMER_CONTROL_REG_TIMER_ENABLE_Mask;
    }
    else
    {
        /// TIMER will stop work.
		cpu_prevent_sleep_clear(msk);
        timerx->ControlReg &= ~TIMER_CONTROL_REG_TIMER_ENABLE_Mask;
    }
}

/*****************************************************************************
 函 数 名  : example_timer_set
 功能描述  : 定时器启动
 输入参数  : functional_state_t enable  
 输出参数  : 无
*****************************************************************************/
void user_timer_set(timer_idx_t id,functional_state_t enable)
{
	timer_type_def *timer[]={
		TIMER0,
		TIMER1,
		TIMER2,
		TIMER3,
	};
	
	cpu_prevent_sleep_t timer_prev[] = {
		TIMER0_ONGOING,
		TIMER1_ONGOING,
		TIMER2_ONGOING,
		TIMER3_ONGOING
	};

	if(enable){
		dbg_printf("Timer%d Start\n",id);
		timer_enable_ctrl_cmd(timer[id], TIMER_START);
		cpu_prevent_sleep_set(timer_prev[id]);			//
	}else{
		dbg_printf("Timer%d Stop\n",id);
		timer_enable_ctrl_cmd(timer[id], TIMER_STOP);
		cpu_prevent_sleep_clear(timer_prev[id]);			//
	}
}





//=========================================================================
//****	定时器应用举例
//****
//****
//=========================================================================
void example_timer_cbk(timer_idx_t id)
{
	const char *timer[4] = {
		"*",
		"#",
		"^",
		"@",
	};
	dbg_block_printf((char *)timer[id]);
}





/*****************************************************************************
 函 数 名  : user_timer_example
 功能描述  : 定时器应用举例
 输入参数  : void  
 输出参数  : 无
 返 回 值  : 
*****************************************************************************/
void user_timer_example(void)
{
	dbg_block_printf("\napp example timer ready \n");
	
	timer_config_t  timer_param;							//定时器

//【1】 开启定时器0 时钟	
	system_clock_config(ws_timer0,ENABLE);

//【2】 开启定时器0 中断
	nvic_init_type_def nvic_init_structure;
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
	nvic_init_structure.nvic_irq_channel_preemption_priority	= 1;
	nvic_init_structure.nvic_irq_channel_subpriority			= 0;
	nvic_init_structure.nvic_irq_channel_cmd					= ENABLE; 
	nvic_init_structure.nvic_irq_channel 						= Timer0_IRQn;
	nvic_init(&nvic_init_structure);

//【3】 初始化定时器参数以及注册回调函数
	timer_param.timer_idx 					= IDX_TIMER0; 							// timer 0
	timer_param.timer_param.timer_period 	= 2000* 16000;				// 100 ms
	timer_config(TIMER0, &timer_param, example_timer_cbk);
	
//【4】 使能定时器
	user_timer_set(IDX_TIMER0,ENABLE);		


//【5】 开启定时器1 时钟	
// 和timer 1 共 时钟及分屏器，因此不在初始化

//【6】 开启定时器1 中断
	nvic_init_structure.nvic_irq_channel 						= Timer1_IRQn;
	nvic_init(&nvic_init_structure);

//【7】 初始化定时器参数以及注册回调函数
	timer_param.timer_idx 					= IDX_TIMER1; 				// timer 0
	timer_param.timer_param.timer_period 	= 2000* 16000;				// 100 ms
	timer_config(TIMER1, &timer_param, example_timer_cbk);
	
//【8】 使能定时器
	user_timer_set(IDX_TIMER1,ENABLE);		


//【9】 开启定时器2 时钟	
	system_clock_config(ws_timer2,ENABLE);

//【10】 开启定时器2 中断
	nvic_init_structure.nvic_irq_channel 						= Timer2_IRQn;
	nvic_init(&nvic_init_structure);

//【11】 初始化定时器参数以及注册回调函数
	timer_param.timer_idx 					= IDX_TIMER2; 							// timer 0
	timer_param.timer_param.timer_period 	= 2000* 16000;				// 100 ms
	timer_config(TIMER2, &timer_param, example_timer_cbk);
	
//【12】 使能定时器
	user_timer_set(IDX_TIMER2,ENABLE);		


//【13】 开启定时器3 时钟	
// 和timer 2 共 时钟及分屏器，因此不在初始化

//【6】 开启定时器3 中断
	nvic_init_structure.nvic_irq_channel 						= Timer3_IRQn;
	nvic_init(&nvic_init_structure);

//【14】 初始化定时器参数以及注册回调函数
	timer_param.timer_idx 					= IDX_TIMER3; 							// timer 0
	timer_param.timer_param.timer_period 	= 2000* 16000;				// 100 ms
	timer_config(TIMER3, &timer_param, example_timer_cbk);
	
//【15】 使能定时器
	user_timer_set(IDX_TIMER3,ENABLE);	

}

