/********************************************************************
  Copyright (c) 2021 Xiangyu Medical Co.，Ltd. All rights reserved.
  FileName : drv_saadc.c
  Author   : zhangdawei
  Version  : V1.0
  Date     :
  Note     :
  History  :
********************************************************************/
/* Includes ------------------------------------------------------*/
#include "nrf_drv_ppi.h"
#include "app_timer.h"
#include "bsp_btn_ble.h"
#include "drv_saadc.h"
#include "timer.h"
#include "string.h"
#include "drv_uart.h"
#include "nrf_drv_ppi.h"
#include "IIR.h"
/* Private define ------------------------------------------------*/
/* Private typedef -----------------------------------------------*/
#define SAMPLES_BUFFER_LEN 10
/* Private constants ---------------------------------------------*/
//定义Timer1的驱动程序实例。驱动程序实例的ID对应Timer的ID，如NRF_DRV_TIMER_INSTANCE(1)对应Timer1
const nrfx_timer_t TIMER_ADC = NRF_DRV_TIMER_INSTANCE(4);
static nrf_ppi_channel_t m_ppi_channel5;
const nrfx_timer_t TIMER3_RMS = NRFX_TIMER_INSTANCE(3);      //读取rms值的定时器3
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_BUFFER_LEN];
/* Private variables ---------------------------------------------*/
/* Private function prototypes -----------------------------------*/
/* Public constants ----------------------------------------------*/
/* Public variables ----------------------------------------------*/
//电池电压回调函数，堵塞模式，不需要事件，定义空的事件回调函数
void saadc_battery_callback(nrfx_saadc_evt_t const * p_event){}
//刺激反馈电压，堵塞模式，不需要事件，定义空的事件回调函数
void saadc_stimulate_callback(nrfx_saadc_evt_t const * p_event){}
    /********************************************************************
* name         : void battery_adc_init(void)
* description  : ADC初始化,刺激电压检测、电池电压检测、电极脱落电压检测
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void battery_adc_init(void)
{
	ret_code_t err_code;
    
	//初始化SAADC，注册事件回调函数。空函数即可
    err_code = nrf_drv_saadc_init(NULL, saadc_battery_callback);
    APP_ERROR_CHECK(err_code);
    
	//配置通道1，输入引脚为AIN7，电池电压
    nrf_saadc_channel_config_t channeltwo_config =
        NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);

    err_code = nrfx_saadc_channel_init(SAADC_BATTERY_CHANNEL, &channeltwo_config);
    APP_ERROR_CHECK(err_code);
    
	// //配置通道2，输入引脚为AIN4，电极片脱落电压检测
    // nrf_saadc_channel_config_t channelthree_config =
    //     NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);

	// //初始化SAADC通道3
    // err_code = nrfx_saadc_channel_init(SAADC_ELECTRODE_CHANNEL, &channelthree_config);
    // APP_ERROR_CHECK(err_code);
}


// 如需更高精度非线性计算（示例）
float nonlinear_percentage(float voltage) {
    // 三元锂电池的典型放电曲线拟合多项式
    float p = (voltage - 3.4f) / 0.8f;  // 归一化到[0,1]
    return 100 * (1.0f - 0.2f*p - 0.8f*p*p); 
}

// 锂电池电量计算函数
// 输入：当前电压（单位：伏特）
// 输出：电量百分比（0~100）
int calculate_battery_percentage(float voltage) 
{
    // 定义电压范围
    const float VOLTAGE_MIN = 3.4f;  // 0%电量对应电压
    const float VOLTAGE_MAX = 4.195f;  // 100%电量对应电压
    
    // 边界检查
    if (voltage <= VOLTAGE_MIN) {
        return 0;
    } else if (voltage >= VOLTAGE_MAX) {
        return 100;
    }
    
    // 线性插值计算百分比（可根据实际放电曲线修改算法）
    float percentage = (voltage - VOLTAGE_MIN) / (VOLTAGE_MAX - VOLTAGE_MIN) * 100.0f;
    
    // 四舍五入取整
    return (int)(percentage + 0.5f);
}

/********************************************************************
* name         : void CalculateBatteryPower(void)
* description  : 计算电池电量（0-100） 
* Input        : void
* Output       : void
* Return       : void
********************************************************************/

void CalculateBatteryPower(void)
{
	uint16_t Adctemp;
	nrf_saadc_value_t Battery_Saadc_Value;
	//启动一次ADC采样,存在Battery_Saadc_Value中
    nrfx_saadc_sample_convert(SAADC_BATTERY_CHANNEL, &Battery_Saadc_Value);
	 
	Adctemp = ((Battery_Saadc_Value * 3600) / 16384);

    static float lastBatteryPercentage = 100;
    int temp = calculate_battery_percentage(Adctemp * 5.12557);

    if(Uncharged == ChargeState) //如果没有处于充电状态，不允许电量上升，只能下降
    {
        if(temp < lastBatteryPercentage)
            Battery_Percentage = temp;
    }
    else
    {
        Battery_Percentage = temp;
    }
    lastBatteryPercentage = Battery_Percentage;
}

short short_to_big_endian(short value) 
{
	uint8_t buf[2];
	short resultShort;
    buf[0] = (value >> 8) & 0xFF;  // 高字节（Big-Endian 第一个字节）
    buf[1] = value & 0xFF;         // 低字节（Big-Endian 第二个字节）
	memcpy(&resultShort,buf,2);
	return resultShort;
}

/********************************************************************
* name         : void rms_saadc_callback(nrfx_saadc_evt_t const * p_event)
* description  : 肌电采集SAADC事件回调函数，只有一个缓存填满后才会进入事件回调函数
* Input        : nrfx_saadc_evt_t const * p_event：saadc事件
* Output       : void
* Return       : 
********************************************************************/

void rms_saadc_callback(nrfx_saadc_evt_t const * p_event)
{
	static float32_t AdcFilter_g[AD_RAW_MAX] __attribute__((aligned(4)));
    float32_t outFilter __attribute__((aligned(4)));
	float32_t vol __attribute__((aligned(4)));
    static emg_data_t emgData=
    {
        .emgCnt = 0
    };

	if(p_event->type == NRF_DRV_SAADC_EVT_DONE)
	{
		ret_code_t err_code;
		err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_BUFFER_LEN);
		APP_ERROR_CHECK(err_code);		
	}

    for(int i = 0; i < SAMPLES_BUFFER_LEN; i++)
    {
        if(p_event->data.done.p_buffer[i] < 0)
            vol = 0;
        else
        {
			vol = (p_event->data.done.p_buffer[i]*3600/16384) - 1545; //
        }
        bs_bp(&vol, &outFilter); //5.6us
	    if(emgData.emgCnt < AD_RAW_MAX) //防止溢出
		    AdcFilter_g[emgData.emgCnt] = outFilter;

        emgData.emgCnt++;
        if(emgData.emgCnt >= AD_RAW_MAX)
        {
            emgData.emgCnt=0;
            float32_t temp __attribute__((aligned(4)));
            arm_rms_f32(AdcFilter_g, AD_RAW_MAX, &temp);//6us
			
			emgData.EmgValue = temp*0.8806 - 3.028;
			if(emgData.EmgValue < 0)
				emgData.EmgValue = 0;
//			if(temp < 0) 
//				emgData.EmgValue = 0;
//			else 
//				emgData.EmgValue = 0.6722 * temp + 3.7097;
		
            uint16_t outfRms;
            outfRms = (short)emgData.EmgValue;
            outfRms = short_to_big_endian(outfRms);
            ble_send_rms_data(outfRms);
        }

        //ble_send_rms_data(save_value[i]);
    }

    

}

void timer3_rms_handler(nrf_timer_event_t event_type, void* p_context)
{

}

/********************************************************************
* name         : void timer3_rms_init(void)
* description  : 定时器1初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void timer3_rms_init(void)
{
	uint32_t err_code = NRF_SUCCESS;
	uint32_t time_us = 500; //采样频率2kHz
	uint32_t time_ticks;
	nrfx_timer_config_t timer3_cfg = NRFX_TIMER_DEFAULT_CONFIG;
	err_code = nrfx_timer_init(&TIMER3_RMS, &timer3_cfg, timer3_rms_handler);
	APP_ERROR_CHECK(err_code);
	time_ticks = nrfx_timer_us_to_ticks(&TIMER3_RMS, time_us);
	nrfx_timer_extended_compare(
		&TIMER3_RMS, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
}
/********************************************************************
* name         : void timer3_rms_start(void)
* description  : 开启定时器1
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void timer3_rms_start(void)
{
	nrfx_timer_enable(&TIMER3_RMS);
}
/********************************************************************
* name         : void timer3_rms_stop(void)
* description  : 停止定时器1
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void timer3_rms_stop(void)
{
	nrfx_timer_disable(&TIMER3_RMS);	
}

/********************************************************************
* name         : void PPIEegAdcInit(void)
* description  : ADCPPI通道初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void PPIEegAdcInit(void)
{
    uint32_t err_code = NRF_SUCCESS;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
    //分配PPI通道，PPI通道的分配是由驱动函数完成的，分配的通道号保存到my_ppi_channel1中
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel5);
    APP_ERROR_CHECK(err_code);
    //分配PPI通道的EEP和TEP
    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel5, 
                                          nrf_drv_timer_event_address_get(&TIMER3_RMS, NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_saadc_sample_task_get());
    APP_ERROR_CHECK(err_code);
    //使能PPI通道
    err_code = nrf_drv_ppi_channel_enable(m_ppi_channel5);
    APP_ERROR_CHECK(err_code);
}

/********************************************************************
* name         : void rms_saadc_init(void)
* description  : 肌电采集saadc初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void rms_saadc_init(void)
{
	ret_code_t err_code;
	nrf_drv_saadc_uninit();   //先反初始化	
	//配置通道0，输入引脚为AIN3，采集信号
	nrf_saadc_channel_config_t channel_config = 
	    NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
	//初始化SAADC，注册事件回调函数。
	err_code = nrf_drv_saadc_init(NULL, rms_saadc_callback);
    APP_ERROR_CHECK(err_code);
	//初始化SAADC通道0
    err_code = nrfx_saadc_channel_init(SAADC_RMS_SAMPLE_CHANNEL, &channel_config);
    APP_ERROR_CHECK(err_code);
    //配置缓存1，将缓存1地址赋值给SAADC驱动程序中的控制块m_cb的一级缓存指针
		err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_BUFFER_LEN);
    APP_ERROR_CHECK(err_code);
    //配置缓存2，将缓存1地址赋值给SAADC驱动程序中的控制块m_cb的二级缓存指针
    err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_BUFFER_LEN);
    APP_ERROR_CHECK(err_code);
}


// 电极脱落检测
void ElectFallOff(void)
{

}
/********************************************************************
* name         : void timer4_output_ctrl_handler(nrf_timer_event_t event_type, void* p_context)
* description  : 变压器电压读取、变压器开关控制、脱落检测、刺激自调节
* Input        : nrf_timer_event_t event_type：定时器事件类型
				 void* p_context
* Output       : void
* Return       : 
********************************************************************/
void timer1_output_ctrl_handler(nrf_timer_event_t event_type, void* p_context)
{
	switch(event_type)
	{
		case NRF_TIMER_EVENT_COMPARE0:
                //ElectFallOff();
			break;
		default:
			break;
	}
}
/********************************************************************
* name         : void timer1_output_ctrl_init(void)
* description  : 输出控制定时器初始化
* Input        : void
* Output       : void
* Return       : 
********************************************************************/
void timer1_output_ctrl_init(void)
{
    ret_code_t err_code = NRF_SUCCESS;
    uint32_t time_us = 50;
    uint32_t time_ticks;
    
    nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
    
    err_code = nrfx_timer_init(&TIMER_ADC, &timer_cfg, timer1_output_ctrl_handler);
    APP_ERROR_CHECK(err_code);
    
	  //定时时间(单位us)转换为ticks
	time_ticks = nrfx_timer_us_to_ticks(&TIMER_ADC, time_us);
    //设置定时器捕获/比较通道及该通道的比较值，使能通道的比较中断
    nrfx_timer_extended_compare(
         &TIMER_ADC, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    nrfx_timer_enable(&TIMER_ADC);
}






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