/* Includes ------------------------------------------------------------------*/
#include "power.h"
#include "include.h"

#if ARCH_MODE == NRF52832_Slave_Mode
#include "delay.h"
#include "InnerFlash.h"
#include "rotation.h"
//#include "led.h"
//#include "74hc595.h"

#if MOTION_SENSOR_TYPE == MOTION_SENSOR_TYPE_9X_ACCEL_GYRO_MAG
#include "nrf_mpu9250_twi_drv.h"
#endif
#include "nrf_drv_saadc.h"
#include "app_uart.h"
#include "ADC.h"
#include "Timer.h"
#include "beep.h"
#include "button.h"
#include "nrf_drv_rng.h"

#elif ARCH_MODE == NRF51822_Peripheral_Mode || ARCH_MODE == NRF51802_Peripheral_Mode
#include "ADC.h"
#include "Timer.h"
#if HW_VERSION != HW_VERSION_BC4_V10 && HW_VERSION != HW_VERSION_BC4J_V10
#include "nrf_drv_rng.h"
#endif
#include "wireless.h"
#include "rotation.h"

#endif

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/* Extern variables ---------------------------------------------------------*/
extern void sleep_mode_enter(void);
extern void advertising_start(bool erase_bonds);
extern void advertising_stop(void);
extern void disconnect_all_ble_connections(void);
extern void set_ble_tx_power_high(void);
extern void set_ble_tx_power_low(void);

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

u8 keyMotionValid_Flag = false;  //电源按键有效标志

uint8_t PowerKeyKeepTime = 0; //电源按键按键计时 单位s
bool SYS_POWER_ON_OFF_FLAG = false;  //判断是否为开机第一次检测 标志位

volatile u8 chargeDoingLedShineTimeout_Flag = true;			//充电中led提示超时标志，超时后关闭led提示  true=超时
volatile u8 chargeFinishedLedShineTimeout_Flag = true;		//充电满led提示超时标志，超时后关闭led提示  true=超时

volatile u8 ChargeDoingKeyEN_Flag = false; 					//充电中检测IO 状态标志 true=充电中
volatile u8 ChargeFinishedKeyEN_Flag = false; 				//充电满状态检测IO 状态标志 true=充电满

PWR_CHARGE_MODE_ENUM chg_mod_last = PWR_CHARGE_MODE_MIN;
s8 chargeCancelOnce_Flag = false;   //充电拔出允许提示一次标志

#if ARCH_MODE == NRF52832_Slave_Mode
#define NRF52_RAM_POWERON_RENTENTIONON  				  POWER_RAM_POWER_S0POWER_On      << POWER_RAM_POWER_S0POWER_Pos      \
														| POWER_RAM_POWER_S1POWER_On      << POWER_RAM_POWER_S1POWER_Pos      \
														| POWER_RAM_POWER_S0RETENTION_On  << POWER_RAM_POWER_S0RETENTION_Pos  \
														| POWER_RAM_POWER_S1RETENTION_On  << POWER_RAM_POWER_S1RETENTION_Pos; 
												
#define NRF52_RAM_POWERON_RENTENTIONOFF 				  POWER_RAM_POWER_S0POWER_On      << POWER_RAM_POWER_S0POWER_Pos      \
														| POWER_RAM_POWER_S1POWER_On      << POWER_RAM_POWER_S1POWER_Pos      \
														| POWER_RAM_POWER_S0RETENTION_Off << POWER_RAM_POWER_S0RETENTION_Pos  \
														| POWER_RAM_POWER_S1RETENTION_Off << POWER_RAM_POWER_S1RETENTION_Pos;														
												
#define NRF52_ONRAM0_OFFRAM0    POWER_RAM_POWER_S0POWER_Off     << POWER_RAM_POWER_S0POWER_Pos      \
												      | POWER_RAM_POWER_S1POWER_Off     << POWER_RAM_POWER_S1POWER_Pos;
void keep_RAM_retention(void)
{
	uint8_t i = 0;
		
	//RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode
	*(volatile uint32_t *)0x40000EE4 = (*(volatile uint32_t *)0x10000258 &0x0000004F);

	
	//Keep RAM block on in system ON Mode
	NRF_POWER->RAMON = (u32)0x00000003UL;
	NRF_POWER->RAMONB = (u32)0x00000003UL;  
	
	//Keep RAM section Sn ON in System ON mode
	for(i = 0; i < 8; i++)
	{
		NRF_POWER->RAM[i].POWER = NRF52_RAM_POWERON_RENTENTIONOFF;   //keep all RAM S0/S1 ON and No Retention when SYSTEM OFF
	}
	NRF_POWER->RAM[7].POWER = NRF52_RAM_POWERON_RENTENTIONON;	//keep RAM7 S1 retention when SYSTEM OFF
	
	//Reset from pin-reset detected  
	//Reset due to wake up from System OFF mode when wakeup is triggered from DETECT signal from GPIO
	//reset from pin / soft / gpio
	NRF_POWER->RESETREAS = (u32)0x00010005UL; 
	
	//Enable constant latency mode
    NRF_POWER->TASKS_CONSTLAT = (u32)0x01UL;
		
}

void init_power_mode(void)
{
#if HW_VERSION == HW_VERSION_BC_PS_V21
	// Internal	DCDC Power converter Select
    NRF_POWER->DCDCEN = (1 ? POWER_DCDCEN_DCDCEN_Enabled : POWER_DCDCEN_DCDCEN_Disabled) << POWER_DCDCEN_DCDCEN_Pos;
#endif

}
/*
#define RAM_STORAGE_ADDRESS		(0X2000F000UL)

typedef struct
{
	
}RETENTION_PARAMS_STRUCT;

#define 
*/
//从内存读取数据
void recover_data_from_ram(void)
{
	
}


//为了关机关掉所有led
void offAllLedsForSystemOff(void)
{
	//shutdown_all_leds();
//	clear_all_serial_leds_ctl_pins();
}
#endif

//进入系统睡眠状态
void enterSystemOff(void)
{
#if ARCH_MODE == NRF52832_Slave_Mode
    offAllLedsForSystemOff();
    PCB_BASE3V3PWR_OFF;
    disable_ring();
    uninit_rotation_gpio();
    nrf_drv_rng_uninit();
    //nrf_drv_ppi_uninit();
#if MOTION_SENSOR_TYPE == MOTION_SENSOR_TYPE_9X_ACCEL_GYRO_MAG
    mpu9520_twi_uninit();
#endif
    nrf_drv_saadc_uninit();
#if UART_ENABLED
    app_uart_close();
    NRF_UART0->ENABLE = 0;
    NRF_UARTE0->ENABLE = 0;
    NVIC_ClearPendingIRQ(UARTE0_UART0_IRQn);	
#endif        
	//uninit_beep_timer();
	//uninit_public_timer();
	//uninit_saadc_timer();
	//NRF_RADIO->POWER = 0;
    sleep_mode_enter();
    
    NRF_POWER->SYSTEMOFF = 1;
	delay_ms(1000);
#elif ARCH_MODE == CC254X_Peripheral_Mode
    
#elif ARCH_MODE == NRF51822_Peripheral_Mode
    uninit_rotation_gpio();
	
    sleep_mode_enter();
    
    NRF_POWER->SYSTEMOFF = 1;
#elif ARCH_MODE == NRF51802_Peripheral_Mode
    
#endif

}

//进入系统关机状态
void shutDown(void)
{
#if ARCH_MODE == NRF52832_Slave_Mode
    //关机前反馈App
    sprintf((char *)debug_str,"SDOK");
    RfSend(80,(char *)debug_str,getStrLen((char *)debug_str));
    

    
    //提示关机声音
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
//    ring_notice(MUSIC_NOTICE_TYPE_3, 1);
#else
//    ring_notice(MUSIC_NOTICE_TYPE_game_over, 3);
#endif

#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	//扬声器进入低功耗模式
	JQSW_SendCmd(JQSW_CMD_Sleep);
#endif    

    
#elif ARCH_MODE == NRF51802_Peripheral_Mode
	
#endif    
}

//系统重启
void systemReset(void)
{
	u8 sDataBuf[] = "RST";
	RfSend(80,(char *)sDataBuf,getStrLen((char *)sDataBuf));
	
	//NVIC_SystemReset();
}

/************************************************************
	使能充电中状态标志
************************************************************/
void enable_ChargeDoingKeyFlag(void)
{
	ChargeDoingKeyEN_Flag = true;					//充电中检测到标志
	chargeDoingLedShineTimeout_Flag = false;		//充电中led提示超时标志状态切换为未超时
	chargeDoingLedShineTimeout.cnt = 0;				//清空超时计数
#if ARCH_MODE == NRF52832_Slave_Mode
//	clearShiningChargeDoingLeds_Status();			//清空充电中led提示阶段标志
#endif        
	ChargeFinishedKeyEN_Flag = false;				//检测到充电中，将充电满标志清空
#if ARCH_MODE == NRF52832_Slave_Mode
	//shutdown_all_leds();
#endif        
}

/************************************************************
	取消充电中状态标志
************************************************************/
void disable_ChargeDoingKeyFlag(void) 
{
	ChargeDoingKeyEN_Flag = false;
	chargeDoingLedShineTimeout_Flag = true;
#if ARCH_MODE == NRF52832_Slave_Mode
	//shutdown_all_leds();
#endif        
}

/************************************************************
	使能充电满状态标志
************************************************************/
void enable_ChargeFinishedKeyFlag(void)
{
	ChargeFinishedKeyEN_Flag = true;				//充电满检测到标志
	chargeFinishedLedShineTimeout_Flag = false;		//充电满led提示超时标志状态切换为未超时
	chargeFinishedLedShineTimeout.cnt = 0;			//清空超时计数
	ChargeDoingKeyEN_Flag = false;					//检测到充电满，将充电中标志清空
#if ARCH_MODE == NRF52832_Slave_Mode
	//shutdown_all_leds();
#endif        
}

/************************************************************
	取消充电满状态标志
************************************************************/
void disable_ChargeFinishedKeyFlag(void) 
{
	ChargeFinishedKeyEN_Flag = false;
	chargeFinishedLedShineTimeout_Flag = true;
#if ARCH_MODE == NRF52832_Slave_Mode
	//shutdown_all_leds();
#endif        
}

/************************************************************
	充电检测并通过led显示充电过程
************************************************************/
void doChargeDoingKeyMotion(PWR_CHARGE_MODE_ENUM *chg_mod)
{
	switch(*chg_mod)
	{
	case PWR_CHARGE_MODE_DOING:
		disable_ChargeFinishedKeyFlag(); 	//取消充电满状态标志
		enable_ChargeDoingKeyFlag(); 		//使能充电中状态标志
		break;
	case PWR_CHARGE_MODE_FINISH:
		disable_ChargeDoingKeyFlag();  		//取消充电中状态标志
		enable_ChargeFinishedKeyFlag(); 	//使能充电满状态标志
		break;
	case PWR_CHARGE_MODE_CACEL:
		if(true == chargeCancelOnce_Flag)    //允许拔出提示一次
		{
			chargeCancelOnce_Flag = false;
			disable_ChargeFinishedKeyFlag(); 	//取消充电满状态标志
			disable_ChargeDoingKeyFlag();  		//取消充电中状态标志
		}			
		break;
	case PWR_CHARGE_MODE_BATERR:
		chargeCancelOnce_Flag = false;
		disable_ChargeFinishedKeyFlag(); 	//取消充电满状态标志
		disable_ChargeDoingKeyFlag();  		//取消充电中状态标志			
		break;
	default:
		break;
	}

	chg_mod_last = *chg_mod;
}

/************************************************************
	检测充电中、充电满led提示超时
************************************************************/
void periodDetectChargeShiningTimeout(void)
{
	if(true == ChargeDoingKeyEN_Flag)   		//充电中状态才检测超时
	{
		if(true == add_STATUS_CTL_STRUCT(&chargeDoingLedShineTimeout))
		{
			chargeDoingLedShineTimeout_Flag = true;
#if ARCH_MODE == NRF52832_Slave_Mode
	//shutdown_all_leds();
#endif        
		}
	}
	if(true == ChargeFinishedKeyEN_Flag)  		//充电满状态才检测超时
	{
		if(true == add_STATUS_CTL_STRUCT(&chargeFinishedLedShineTimeout))
		{
			chargeFinishedLedShineTimeout_Flag = true;
#if ARCH_MODE == NRF52832_Slave_Mode
	//shutdown_all_leds();
#endif        
		}
	}
}

/************************************************************
	定时执行充电指示灯闪烁  100ms计时累加一次
************************************************************/
void cycleChargeShiningExecute(void)
{
	if(false == chargeStatusDisplay_EN_Flag)
	{
		return;
	}
	
	if(false == chargeFinishedLedShineTimeout_Flag)  	//充电满提示灯未超时
	{
		chargeDoingLedShineTimeout_Flag = true;			//充电满，自动关闭充电中led指示灯
		if(true == add_STATUS_CTL_STRUCT(&chargeFinishedLedShineInterval))
		{
#if ARCH_MODE == NRF52832_Slave_Mode
			//doShiningChargeFinishedLeds();  			//充电满提示灯执行闪烁
#endif        
		}
	}
	else
	{
		chargeFinishedLedShineTimeout_Flag = true;		//充电中，自动关闭充电满led指示灯
		if(false == chargeDoingLedShineTimeout_Flag)  	//充电中提示灯未超时
		{
			if(true == add_STATUS_CTL_STRUCT(&chargeDoingLedShineInterval))
			{
				chargeCancelOnce_Flag = true;    		//开启拔出提示一次标志
#if ARCH_MODE == NRF52832_Slave_Mode
				//doShiningChargeDoingStageLeds();  		//充电中提示灯执行闪烁
#endif        
			}
		}
	}
}

//检查是否允许进入关机状态，如果允许，关机
void cycleCheckSystemOff(void)
{
	if(false == disallowShutdownAfterBootTimeout.isTrigedOnceFlag)
	{
		if(false == add_STATUS_CTL_STRUCT(&disallowShutdownAfterBootTimeout)) //禁止开机时间段内，不允许关机
		{
			disAllowSystemOff();	
		}
	}
	
	//充电中，不允许关机
	if(true == ChargeDoingKeyEN_Flag)   		//充电中状态才检测超时
	{
		return;
	}
	
		
	//检查是否到了关机时刻
	if(true == add_STATUS_CTL_STRUCT(&isAllowSystemOff))
	{
		if(true == isAllowSystemOff_EN_Flag)
		{
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
			//扬声器进入低功耗模式
			JQSW_SendCmd(JQSW_CMD_Sleep);
#endif
#if POWER_WORKING_MODE == POWER_TIMEOUT_OFF_MODE
			shutDown();  //关机
#elif POWER_WORKING_MODE == POWER_LONGTIME_ON_MODE
			//低功耗运行
#endif
		}
		else		//本次不允许关机，等待下一个周期
		{
			allowSystemOff();
		}
	}
}

//不允许定时关机，将关机使能标志位清空
void disAllowSystemOff(void)
{
	isAllowSystemOff_EN_Flag = false;						//禁止关机标志
	isAllowSystemOff.cnt = 0;  								//倒计时从头开始
}

//允许定时关机，将关机使能标志位使能
void allowSystemOff(void)
{
	isAllowSystemOff_EN_Flag = true;						//允许关机标志
	isAllowSystemOff.cnt = isAllowSystemOff.cntMax - 2;  	//倒计时n*4s 关机
}

u16 shutDown_cnt = 0;
//处理关机按键
void do_power_key_press(void)
{
#if POWER_WORKING_MODE == POWER_TIMEOUT_OFF_MODE
	//长按开关机键，关机
	shutDown();			//不关机模式下，按键关机禁用	
#endif
}

//获取电池剩余电量百分比
void GetBatteryPowerLeftPercent(u8 *percent)
{
#if ARCH_MODE == CC254X_Peripheral_Mode
    *percent = 101;
#else
    GetBatteryVoltagePercent(percent);
#endif
}

#if HW_VERSION == HW_VERSION_BC_PS_V20 || HW_VERSION == HW_VERSION_BC_PS_V21
s8 isAdvertiseStoped_Flag = false;
//进入待机模式
s8 enter_standby_mode(void)
{
	offAllLedsForSystemOff();
    disable_ring();
	//application_timers_stop_for_power_saving();
	disable_public_timer();
	disable_beep_timer();
	disable_saadc_timer();
	//uninit_rotation_gpio();
	//uninit_general_key_button();
	PCB_BASE3V3PWR_OFF;
	//disconnect_all_ble_connections();
	set_ble_tx_power_low();
	
	/*if(false == isAdvertiseStoped_Flag)
	{
		advertising_stop();
		isAdvertiseStoped_Flag = true;
	}*/
	
	return true;
}

//离开待机模式
s8 leave_standby_mode(void)
{
	PCB_BASE3V3PWR_ON;
    enable_ring();
	//application_timers_resume_from_power_saving();
	enable_public_timer();
	enable_beep_timer();
	enable_saadc_timer();
	//init_rotation_gpio();
	//init_general_key_button();
	offAllLedsForSystemOff();
	set_ble_tx_power_high();

	/*if(true == isAdvertiseStoped_Flag)
	{
		advertising_start(true);
		isAdvertiseStoped_Flag = false;
	}*/
	
	return true;
}

#endif

/*********************************************end of file*********************************************/
