/********************************************************************
  Copyright (c) 2021 Xiangyu Medical Co.，Ltd. All rights reserved.
  FileName : timer.c
  Author   : zhangdawei
  Version  : V1.0
  Date     :
  Note     :
  History  :
********************************************************************/
/* Includes ------------------------------------------------------*/
#include "nrf_drv_pwm.h"
#include "drv_uart.h"
#include "IoControl.h"
#include "timer.h"
#include "nrf_delay.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_gpiote.h"
/* Private define ------------------------------------------------*/
/* 定义APP定时器 */
APP_TIMER_DEF(detect_button_100ms);
#define DETECT_BUTTON    APP_TIMER_TICKS(100)


/* Private typedef -----------------------------------------------*/
//定义名称为m_pwm_add的驱动程序实例
static nrfx_pwm_t m_pwm_dac       = NRFX_PWM_INSTANCE(1);
static nrfx_pwm_t m_pwm0          = NRFX_PWM_INSTANCE(0);
static nrfx_pwm_t m_pwm2          = NRFX_PWM_INSTANCE(2);
/* Private constants ---------------------------------------------*/

/* Private variables ---------------------------------------------*/

/* 呼吸灯占空比 */
uint16_t m_step = 150;
/* 存放RunLED占空比的数组 */
static nrf_pwm_values_common_t    seq3_values[M_STEP*2];
//定义PWM序列，该序列必须位于RAM中，因此要定义为static类型
static nrf_pwm_values_common_t    dac_values[] = {CYCLE_CALUE};    //14

static nrf_pwm_values_wave_form_t seq0_current_values[] =
{
	10000 - 600, 
	10000 - 400,
	10000 - 200,      
	10000    //100Hz
};  


static nrf_pwm_values_wave_form_t seq2_current_values[] =
{
	800 - 125, 
	800,
	800,      
	800    //20khz
};  

E_WORK_STATE eRmsState = E_RMS_STOP;

/* Private function prototypes -----------------------------------*/

/* Public constants ----------------------------------------------*/
/* Public variables ----------------------------------------------*/


/********************************************************************
* name         : void acquisition_start(void)
* description  : 开始采集肌电
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void acquisition_start(void)
{
	eRmsState = E_RMS_START;	
//	rms_saadc_init();
    nrf_gpio_pin_set(SAMPLE_POWER_PIN);
    open_acquisition_relay();

	timer3_rms_start();

}

/********************************************************************
* name         : void acquisition_stop(void)
* description  : 停止肌电采集
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void acquisition_stop(void)
{
	timer3_rms_stop();
	eRmsState = E_RMS_STOP;
    nrf_gpio_pin_clear(SAMPLE_POWER_PIN);
    close_acquisition_relay();
}

/********************************************************************
* name         : void stimulate_start(void)
* description  : 开始刺激
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void stimulate_start(void)
{
    acquisition_stop(); //先停止肌电采集
 //   stimulate_stop(); //停止刺激，重新开始刺激

	eRmsState = E_STIM_START;
    open_stimulate_relay();
    pwm0_play();
    pwm2_play();
}

/********************************************************************
* name         : void stimulate_stop(void)
* description  : 停止刺激
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void stimulate_stop(void)
{
	eRmsState = E_STIM_STOP;
    close_stimulate_relay();

}


/********************************************************************
* name         : static void detect_button(void)
* description  : 开关机按键检测处理
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
static void detect_button(void)
{
    static uint8_t CountValue=0;
    if((Bit_RESET == nrf_gpio_pin_read(KEY_PWR_SWITICH))&&((ChargeState == Uncharged))) //检测按键是否按下
    {
        CountValue++;

        if(CountValue == 10)
        {
            if(POWER_CLOSE == DeviceState)           //开机
            {
                DeviceState = POWER_OPEN;
                nrf_gpio_pin_set(KEY_POWER);        //锁定电源键，给MCU供电

                NRF_LOG_INFO("Open!");
                StartAdv();
            }
            else if(POWER_OPEN == DeviceState)       //关机
            {   
                DeviceState = POWER_CLOSE;  
                acquisition_stop();
                NRF_LOG_INFO("Close!");
                nrf_gpio_pin_clear(KEY_POWER);      //断电
            }
        }
    }
    else
    {
        CountValue = 0;
    }
    static uint16_t runBlinkCount = 0;

    if(runBlinkCount == 0 && DeviceState == POWER_OPEN)
        nrf_gpio_pin_set(LED_YELLOW);
    else if(runBlinkCount == 1)
        nrf_gpio_pin_clear(LED_YELLOW);
        
    if(runBlinkCount++ > 8) //1S闪烁一次
    {
        runBlinkCount = 0;
    }

}

/********************************************************************
* name         : static void detect_charging_status(void)
* description  : 充电状态检测处理
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
static void detect_charging_status(void)
{
    static uint8_t CountValue=0;
    if((Bit_RESET == nrf_gpio_pin_read(CHG_MANAGER_CHG))) //检测按键是否按下
    {
        ChargeState = Charging;
    }
    else
    {
        ChargeState = Uncharged;
    }

}

/********************************************************************
* name         : static void Hundredms_handler(void * p_context)
* description  : 检测按键是否长按函数，100ms中断一次，累计计数
* Input        : void *p_context
* Output       : void
* Return       : 
********************************************************************/
static void Hundredms_handler(void * p_context)
{
    //防止编译器警告，同时清晰地的表明p_context未使用，而不是应用程序忽略了。如果应用
	//程序需要使用p_context，则不需要这行代码
	UNUSED_PARAMETER(p_context);
    /* 开机按键检测处理 */
    detect_button();
    /* 电池电量检测 */
	CalculateBatteryPower();
    /* 充电状态检测 */
	detect_charging_status();
	static uint16_t delay_open = 0;
	if(POWER_OPEN == DeviceState && delay_open !=  70 && delay_open++ >60  )
	{
		//acquisition_start();
        stimulate_start();
		delay_open = 70;
	}

}


/********************************************************************
* name         : void AppTimersInit(void)
* description  : 初始化APP定时器模块、创建APP定时器
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void AppTimersInit(void)
{
    
    ret_code_t err_code = app_timer_init();//初始化APP定时器模块
    APP_ERROR_CHECK(err_code);	
    
    err_code = app_timer_create(&detect_button_100ms,
	                            APP_TIMER_MODE_REPEATED,
	                            Hundredms_handler);
    APP_ERROR_CHECK(err_code);
}
/********************************************************************
* name         : void ApplicationTimersStart(void)
* description  : 启动已经创建的的APP定时器
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void ApplicationTimersStart(void)
{
    ret_code_t err_code;

    err_code = app_timer_start(detect_button_100ms, DETECT_BUTTON, NULL);
    APP_ERROR_CHECK(err_code);
}
/********************************************************************
* name         : void PwmDACInit(void)
* description  : 控制DAC的pwm初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void PwmDACInit(void)
{
	//定义PWM初始化配置结构体并初始化参数
    nrfx_pwm_config_t const config0 =
    {
        .output_pins =
        {
            PWM_DAC_GPIO,                      //通道0映射到P   WM_DAC_GPIO，空闲状态输出低电平
            NRFX_PWM_PIN_NOT_USED ,            //通道1不使用
            NRFX_PWM_PIN_NOT_USED ,            //通道2不使用
            NRFX_PWM_PIN_NOT_USED              //通道3不使用
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
        .base_clock   = NRF_PWM_CLK_1MHz,       //PWM时钟频率设置为1MHz  
        .count_mode   = NRF_PWM_MODE_UP,        //向上计数模式
        .top_value    = CYCLE_CALUE,                   //该值为周期值
        .load_mode    = NRF_PWM_LOAD_COMMON,    //通用模式
        .step_mode    = NRF_PWM_STEP_AUTO       //序列中的周期自动推进
    };
    APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm_dac, &config0, NULL));//初始化PWM
}


/********************************************************************
* name         : void PwmDACPlay(void)
* description  : 播放充能PWM
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void PwmDACPlay(void)
{
    //定义PWM播放序列，播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
	  nrf_pwm_sequence_t const seq =
    {
        .values.p_common    = dac_values,//指向PWM序列
        .length             = NRF_PWM_VALUES_LENGTH(dac_values),//PWM序列中包含的周期个数
        .repeats            = 0, //序列中周期重复次数为0
        .end_delay          = 0  //序列后不插入延时
    };
    //启动PWM序列播放，flags设置为NRFX_PWM_FLAG_LOOP：序列播放完成后，自动触发任务重新播放
    (void)nrfx_pwm_simple_playback(&m_pwm_dac, &seq, 1, NRFX_PWM_FLAG_LOOP);
}
void SetPWMValues(uint16_t tempvalue)
{
    *dac_values = CYCLE_CALUE - tempvalue;
}


/********************************************************************
* name         : void PwmDACStop(void)
* description  : 停止播放充能PWM
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void PwmDACStop(void)
{
	nrfx_pwm_stop(&m_pwm_dac,1);
}


/********************************************************************
* name         : void pwm0_common_init(void)
* description  : 电流控制PWM初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void pwm0_common_init(void)
{
			//定义PWM初始化配置结构体并初始化参数
    nrfx_pwm_config_t const config0 =
    {
        .output_pins =
        {
			BASE_WAVE_06_PIN,
			BASE_WAVE_07_PIN,
            BASE_WAVE_08_PIN,
			NRFX_PWM_PIN_NOT_USED
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
        .base_clock   = NRF_PWM_CLK_1MHz,       //PWM时钟频率设置为16MHz  
        .count_mode   = NRF_PWM_MODE_UP,        //向上计数模式
        .top_value    = 0,                      //使用波形装载模式时，该值被忽略
        .load_mode    = NRF_PWM_LOAD_WAVE_FORM, //独立装载模式
        .step_mode    = NRF_PWM_STEP_AUTO       //序列中的周期自动推进
    };
		//初始化PWM
    APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));

    /////////////
    //pwm0_play();
}

/********************************************************************
* name         : void pwm0_play(void)
* description  : 电流控制PWM开始播放
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void pwm0_play(void)
{
     //定义PWM播放序列，播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
	nrf_pwm_sequence_t const seq0 =
	{
		.values.p_wave_form = seq0_current_values,//指向PWM序列
		.length             = NRF_PWM_VALUES_LENGTH(seq0_current_values),//PWM序列中包含的周期个数
		.repeats            = 0, //序列中周期重复次数为0
		.end_delay          = 0  //序列后不插入延时
	};
	//启动PWM序列播放，flags设置为NRFX_PWM_FLAG_LOOP：序列播放完成后，自动触发任务重新播放
		//如改为NRFX_PWM_FLAG_STOP，则播放结束后，PWM停止
	(void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1,
									   NRFX_PWM_FLAG_LOOP);	
}

void pwm0_stop(void)
{
	nrfx_pwm_stop(&m_pwm0, 1);
}

/********************************************************************
* name         : void pwm2_common_init(void)
* description  : 电流控制PWM初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void pwm2common_init(void)
{
			//定义PWM初始化配置结构体并初始化参数
    nrfx_pwm_config_t const config0 =
    {
        .output_pins =
        {
			BOOST_VOLTAGE_CONTROL_PIN,
			NRFX_PWM_PIN_NOT_USED,
            NRFX_PWM_PIN_NOT_USED,             
			NRFX_PWM_PIN_NOT_USED              
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
        .base_clock   = NRF_PWM_CLK_16MHz,       //PWM时钟频率设置为16MHz  
        .count_mode   = NRF_PWM_MODE_UP,        //向上计数模式
        .top_value    = 0,                      //使用波形装载模式时，该值被忽略
        .load_mode    = NRF_PWM_LOAD_WAVE_FORM, //独立装载模式
        .step_mode    = NRF_PWM_STEP_AUTO       //序列中的周期自动推进
    };
		//初始化PWM
    APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm2, &config0, NULL));

    /////////////
    //pwm2_play();
}

/********************************************************************
* name         : void pwm2_play(void)
* description  : 电流控制PWM开始播放
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void pwm2_play(void)
{
     //定义PWM播放序列，播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
	nrf_pwm_sequence_t const seq2 =
	{
		.values.p_wave_form = seq2_current_values,//指向PWM序列
		.length             = NRF_PWM_VALUES_LENGTH(seq2_current_values),//PWM序列中包含的周期个数
		.repeats            = 0, //序列中周期重复次数为0
		.end_delay          = 0  //序列后不插入延时
	};
	//启动PWM序列播放，flags设置为NRFX_PWM_FLAG_LOOP：序列播放完成后，自动触发任务重新播放
		//如改为NRFX_PWM_FLAG_STOP，则播放结束后，PWM停止
	(void)nrfx_pwm_simple_playback(&m_pwm2, &seq2, 1,
									   NRFX_PWM_FLAG_LOOP);
}

void pwm2_stop(void)
{
	nrfx_pwm_stop(&m_pwm2, 1);
}

/********************************************************************
* name         : void GpioteInit(void)
* description  : 刺激的任务GPIOTE初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void GpioteInit(void)
{

}

/********************************************************************
* name         : void PPIPwmInit(void)
* description  : 刺激PWM的PPI初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void PPIPwmInit(void)
{

}

/*************************** END OF FILE ***************************/



