/*
 * @Description: 
 * @Date: 2020-04-17 13:16:16
 * @LastEditors: CK.Zh
 * @LastEditTime: 2021-01-07 18:00:29
 * @FilePath: \NaviKit_stm32\Core\Src\navikit.c
 */
/*
 * navikit.c
 *
 *  Created on: Apr 17, 2020
 *      Author: oarap
 */

#define LOG_TAG "NAVIKIT"

#include "navikit.h"
#include "cmsis_os2.h"                  // ::CMSIS:RTOS2

NaviKit_t NaviKit;

void NaviKit_var_init()
{
	NaviKit.sys.sta = idle;
	NaviKit.sys.next_sta = idle;
	NaviKit.pmb.main_pwr_good = true;
}

void TaskBeep(uint32_t time_ms , uint8_t n)
{
	for(uint8_t i=0;i<n;i++){
		HAL_GPIO_WritePin(SYS_BUZZ_CTL_GPIO_Port,SYS_BUZZ_CTL_Pin, GPIO_PIN_RESET);
		osDelay(time_ms>>1);//equal "time divided by 2"
		HAL_GPIO_WritePin(SYS_BUZZ_CTL_GPIO_Port,SYS_BUZZ_CTL_Pin, GPIO_PIN_SET);
		osDelay(time_ms>>1);//equal "time divided by 2"
	}
}


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(hadc->Instance == ADC1)
	{
		// ADC_CHANNEL_TEMPSENSOR  ADC_CHANNEL_16  /* ADC internal channel (no connection on device pin) */
		// ADC_CHANNEL_VREFINT     ADC_CHANNEL_17  /* ADC internal channel (no connection on device pin) */
		float adc_17_voltage = (float)1.2 / NaviKit.pmb.rails.adc[1];//reference voltage

		NaviKit.pmb.rails.out_24v   = (float)(adc_17_voltage * NaviKit.pmb.rails.adc[2] * 16);
		NaviKit.pmb.rails.out_5v    = (float)(adc_17_voltage * NaviKit.pmb.rails.adc[3] * 8);
		NaviKit.pmb.rails.out_12v   = (float)(adc_17_voltage * NaviKit.pmb.rails.adc[4] * 8);
		NaviKit.pmb.rails.bkp_bat   = (float)(adc_17_voltage * NaviKit.pmb.rails.adc[5] * 8);
		NaviKit.pmb.rails.main_pwr  = (float)(adc_17_voltage * NaviKit.pmb.rails.adc[6] * 16);
	}
}

//温度变化较大时将触发看门狗，进行校准
void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
//		HAL_ADCEx_Calibration_Start(&hadc1);
}


void enter_standby_state(uint16_t delay){
	  log_i("EC enter to STANDBY Mode to save power, see you!");
	  osDelay(delay);
	  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);//Enable PA0 wakeup function
	  __HAL_RCC_RTC_DISABLE();
	  HAL_RCC_DeInit();
	  HAL_PWR_EnterSTANDBYMode();
}
void enter_isp_state()
{
	//write "bios update flag" to bkp register, and reset system
	ISP_Prepare();
}

//timeout:the time of wait
void enter_idle_state(uint16_t delay){
	log_i("Enter to idle state.");
	TaskBeep(50,1);

	PWR_Enable(SOM_SLEEP,true,delay);

    PWR_Enable(USB3_Port4,false, delay);
    PWR_Enable(USB3_Port3,false, delay);
    PWR_Enable(USB3_Port2,false, delay);
    PWR_Enable(USB3_Port1,false, delay);
    PWR_Enable(USB3_Port6,false, delay);
    PWR_Enable(USB3_Port5,false, delay);

    PWR_Enable(USB2_Port6,false, delay);
    PWR_Enable(USB2_Port5,false, delay);
    PWR_Enable(USB2_Port4,false, delay);
    PWR_Enable(USB2_Port3,false, delay);
    PWR_Enable(USB2_Port2,false, delay);
    PWR_Enable(USB2_Port1,false, delay);

    PWR_Enable(SOC_USB3_HUB ,false, delay);
    PWR_Enable(SOC_USB2_HUB ,false, delay);
    PWR_Enable(SOC_USB3_HOST,false, delay);
    PWR_Enable(SOC_USB3_GEC ,false, delay);
    PWR_Enable(SOC_GE_SW    ,false, delay);

    PWR_Enable(SYS_FAN1 ,false , delay);
	PWR_Enable(SYS_FAN2 ,false , delay);
	PWR_Enable(SYS_FAN3 ,false , delay);

    PWR_Enable(SOM_PWR_EN ,false, delay);

	PWR_Enable(PMB_PS_ON ,false , 0);
}

void enter_run_state(uint16_t delay)
{
	log_i("Enter to run state");
	TaskBeep(200,1);

	PWR_Enable(PMB_PS_ON ,true, delay);

  	PWR_Enable(SOM_DFU ,false, 0);		//disable dfu pin
	PWR_Enable(SOM_RESET , false , 0);	//disable reset pin

	PWR_Enable(SYS_FAN1 ,true , delay);
	PWR_Enable(SYS_FAN2 ,true , delay);
	PWR_Enable(SYS_FAN3 ,true , delay);

	PWR_Enable(SOM_PWR_EN , true , delay);

	PWR_Enable(SOC_USB3_HUB ,true , delay);
	PWR_Enable(SOC_USB2_HUB ,true , delay);
	PWR_Enable(SOC_USB3_HOST,true , delay);
	PWR_Enable(SOC_USB3_GEC ,true , delay);
	PWR_Enable(SOC_GE_SW    ,true , delay);

	PWR_Enable(USB2_Port1,true , delay);
	PWR_Enable(USB2_Port2,true , delay);
	PWR_Enable(USB2_Port3,true , delay);
	PWR_Enable(USB2_Port4,true , delay);
	PWR_Enable(USB2_Port5,true , delay);
	PWR_Enable(USB2_Port6,true , delay);

	PWR_Enable(USB3_Port5,true , delay);
	PWR_Enable(USB3_Port6,true , delay);
	PWR_Enable(USB3_Port1,true , delay);
	PWR_Enable(USB3_Port2,true , delay);
	PWR_Enable(USB3_Port3,true , delay);
	PWR_Enable(USB3_Port4,true , delay);

}
void enter_sleep_state(uint16_t delay)
{
	log_i("Enter to sleep state.");
	TaskBeep(50,1);
}
void enter_dfu_state(uint16_t delay)
{

  log_i("Enter to DFU state.");
  TaskBeep(500,3);

  PWR_Enable(PMB_PS_ON , true , delay);

  PWR_Enable(SOM_DFU , true , 0);
  PWR_Enable(SOM_RESET , false , 0);	//disable reset pin

  PWR_Enable(SYS_FAN1 , true , delay);
  PWR_Enable(SYS_FAN2 , true , delay);
  PWR_Enable(SYS_FAN3 , true , delay);

  PWR_Enable(SOM_PWR_EN , true , delay);

}
//para, delay：reset low level signal duration (ms)
void som_reboot(uint16_t delay){
	  log_i("Jetson Nano rebooting...");
		PWR_Enable(SOM_RESET,true,0);
		TaskBeep(100,1);
		PWR_Enable(SOM_RESET,false,0);
}

void PWR_Enable(enum Device_t device,bool en,uint16_t delay){
	bool result = false;
	result = PWR_Enable_IRQ(device,en,0);
	if(result){
		log_v("Device 0x%02X -> %s",device,(en == true) ? "[ON]" : "[OFF]");
		osDelay(delay);
	}else{
		log_e("Power_Enable device parameter is invalid!");
	}
}

//PWR_Enable_IRQ：for interrupt safe reversion
//device power enable or disable
//device: Specified device
//en: enable or disable
//delay: After executing the operation delay (ms)
//return: true-success;false-parameter valid
bool PWR_Enable_IRQ(enum Device_t device,bool en,uint16_t delay){
	switch (device){
		case USB2_Port1:	{HAL_GPIO_WritePin(USB2_VBUS_CTL_1_GPIO_Port,	USB2_VBUS_CTL_1_Pin, 	en);			}break;
		case USB2_Port2:	{HAL_GPIO_WritePin(USB2_VBUS_CTL_2_GPIO_Port,	USB2_VBUS_CTL_2_Pin, 	en);			}break;
		case USB2_Port3:	{HAL_GPIO_WritePin(USB2_VBUS_CTL_3_GPIO_Port,	USB2_VBUS_CTL_3_Pin,	en);			}break;
		case USB2_Port4:	{HAL_GPIO_WritePin(USB2_VBUS_CTL_4_GPIO_Port,	USB2_VBUS_CTL_4_Pin, 	en);			}break;
		case USB2_Port5:	{HAL_GPIO_WritePin(USB2_VBUS_CTL_5_GPIO_Port,	USB2_VBUS_CTL_5_Pin, 	en);			}break;
		case USB2_Port6:	{HAL_GPIO_WritePin(USB2_VBUS_CTL_6_GPIO_Port,	USB2_VBUS_CTL_6_Pin, 	en);			}break;
		case USB3_Port1:	{HAL_GPIO_WritePin(USB3_VBUS_CTL_1_GPIO_Port,	USB3_VBUS_CTL_1_Pin, 	en);			}break;
		case USB3_Port2:	{HAL_GPIO_WritePin(USB3_VBUS_CTL_2_GPIO_Port,	USB3_VBUS_CTL_2_Pin, 	en);			}break;
		case USB3_Port3:	{HAL_GPIO_WritePin(USB3_VBUS_CTL_3_GPIO_Port,	USB3_VBUS_CTL_3_Pin, 	en);			}break;
		case USB3_Port4:	{HAL_GPIO_WritePin(USB3_VBUS_CTL_4_GPIO_Port,	USB3_VBUS_CTL_4_Pin, 	en);			}break;
		case USB3_Port5:	{HAL_GPIO_WritePin(USB3_VBUS_CTL_5_GPIO_Port,	USB3_VBUS_CTL_5_Pin, 	en);			}break;
		case USB3_Port6:	{HAL_GPIO_WritePin(USB3_VBUS_CTL_6_GPIO_Port,	USB3_VBUS_CTL_6_Pin, 	en);			}break;
		case SOC_USB2_HUB:  {HAL_GPIO_WritePin(SOC_U2_HUB_PWR_CTL_GPIO_Port,SOC_U2_HUB_PWR_CTL_Pin, en);			}break;
		case SOC_USB3_HUB:  {HAL_GPIO_WritePin(SOC_U3_HUB_PWR_CTL_GPIO_Port,SOC_U3_HUB_PWR_CTL_Pin, en);			}break;
		case SOC_USB3_HOST: {HAL_GPIO_WritePin(SOC_U3_HOST_PWR_CTL_GPIO_Port,SOC_U3_HOST_PWR_CTL_Pin, en);			}break;
		case SOC_USB3_GEC:  {HAL_GPIO_WritePin(SOC_U3_GEC_PWR_CTL_GPIO_Port,SOC_U3_GEC_PWR_CTL_Pin, en);			}break;
		case SOC_GE_SW:     {HAL_GPIO_WritePin(SOC_GE_SW_PWR_CTL_GPIO_Port,	SOC_GE_SW_PWR_CTL_Pin, 	en);	    	}break;
		case SYS_FAN1:  	{HAL_GPIO_WritePin(SYS_FAN_CTL_1_GPIO_Port,		SYS_FAN_CTL_1_Pin, 		en);			}break;
		case SYS_FAN2:  	{HAL_GPIO_WritePin(SYS_FAN_CTL_2_GPIO_Port,		SYS_FAN_CTL_2_Pin, 		en);			}break;
		case SYS_FAN3:  	{HAL_GPIO_WritePin(SYS_FAN_CTL_3_GPIO_Port,		SYS_FAN_CTL_3_Pin, 		en);			}break;
		case SYS_RUN_LED:  	{HAL_GPIO_WritePin(SYS_RUN_LED_CTL_GPIO_Port,	SYS_RUN_LED_CTL_Pin, 	!en);			}break;
		case SYS_PWR_LED:  	{HAL_GPIO_WritePin(SYS_POWER_LED_CTL_GPIO_Port,	SYS_POWER_LED_CTL_Pin, 	!en);			}break;
		case SOM_PWR_EN:  	{HAL_GPIO_WritePin(SOM_POWER_EN_GPIO_Port,		SOM_POWER_EN_Pin, 		en);			}break;
		case SOM_DFU:  		{HAL_GPIO_WritePin(SOM_FORCE_RECOVERY_GPIO_Port,SOM_FORCE_RECOVERY_Pin, !en);			}break;
		case SOM_RESET: 	{HAL_GPIO_WritePin(SOM_SYS_RESET_GPIO_Port,		SOM_SYS_RESET_Pin, 		!en);			}break;
		case SOM_SLEEP:  	{HAL_GPIO_WritePin(SOM_SLEEP_WAKE_GPIO_Port,	SOM_SLEEP_WAKE_Pin,		!en);			}break;
		case PMB_PS_ON:  	{HAL_GPIO_WritePin(PMB_PS_ON_GPIO_Port,			PMB_PS_ON_Pin, 			en);			}break;
		default:			{return false;										}break;
	}
	osDelay(delay);
	return true;
}

//check device on board power status
bool PWR_Status(enum Device_t device){
    bool sta = false;
    switch (device){
	case USB2_Port1:	{sta = HAL_GPIO_ReadPin(USB2_VBUS_CTL_1_GPIO_Port,USB2_VBUS_CTL_1_Pin);			}break;
	case USB2_Port2:	{sta = HAL_GPIO_ReadPin(USB2_VBUS_CTL_2_GPIO_Port,USB2_VBUS_CTL_2_Pin);			}break;
	case USB2_Port3:	{sta = HAL_GPIO_ReadPin(USB2_VBUS_CTL_3_GPIO_Port,USB2_VBUS_CTL_3_Pin);			}break;
	case USB2_Port4:	{sta = HAL_GPIO_ReadPin(USB2_VBUS_CTL_4_GPIO_Port,USB2_VBUS_CTL_4_Pin);			}break;
	case USB2_Port5:	{sta = HAL_GPIO_ReadPin(USB2_VBUS_CTL_5_GPIO_Port,USB2_VBUS_CTL_5_Pin);			}break;
	case USB2_Port6:	{sta = HAL_GPIO_ReadPin(USB2_VBUS_CTL_6_GPIO_Port,USB2_VBUS_CTL_6_Pin);			}break;
	case USB3_Port1:	{sta = HAL_GPIO_ReadPin(USB3_VBUS_CTL_1_GPIO_Port,USB3_VBUS_CTL_1_Pin);			}break;
	case USB3_Port2:	{sta = HAL_GPIO_ReadPin(USB3_VBUS_CTL_2_GPIO_Port,USB3_VBUS_CTL_2_Pin);			}break;
	case USB3_Port3:	{sta = HAL_GPIO_ReadPin(USB3_VBUS_CTL_3_GPIO_Port,USB3_VBUS_CTL_3_Pin);			}break;
	case USB3_Port4:	{sta = HAL_GPIO_ReadPin(USB3_VBUS_CTL_4_GPIO_Port,USB3_VBUS_CTL_4_Pin);			}break;
	case USB3_Port5:	{sta = HAL_GPIO_ReadPin(USB3_VBUS_CTL_5_GPIO_Port,USB3_VBUS_CTL_5_Pin);			}break;
	case USB3_Port6:	{sta = HAL_GPIO_ReadPin(USB3_VBUS_CTL_6_GPIO_Port,USB3_VBUS_CTL_6_Pin);			}break;
	case SOC_USB2_HUB:  {sta = HAL_GPIO_ReadPin(SOC_U2_HUB_PWR_CTL_GPIO_Port,SOC_U2_HUB_PWR_CTL_Pin);	}break;
	case SOC_USB3_HUB:  {sta = HAL_GPIO_ReadPin(SOC_U3_HUB_PWR_CTL_GPIO_Port,SOC_U3_HUB_PWR_CTL_Pin);	}break;
	case SOC_USB3_HOST: {sta = HAL_GPIO_ReadPin(SOC_U3_HOST_PWR_CTL_GPIO_Port,SOC_U3_HOST_PWR_CTL_Pin);	}break;
	case SOC_USB3_GEC:  {sta = HAL_GPIO_ReadPin(SOC_U3_GEC_PWR_CTL_GPIO_Port,SOC_U3_GEC_PWR_CTL_Pin);	}break;
	case SOC_GE_SW:     {sta = HAL_GPIO_ReadPin(SOC_GE_SW_PWR_CTL_GPIO_Port,SOC_GE_SW_PWR_CTL_Pin);	    }break;
	case SYS_FAN1:  	{sta = HAL_GPIO_ReadPin(SYS_FAN_CTL_1_GPIO_Port,SYS_FAN_CTL_1_Pin);				}break;
	case SYS_FAN2:  	{sta = HAL_GPIO_ReadPin(SYS_FAN_CTL_2_GPIO_Port,SYS_FAN_CTL_2_Pin);				}break;
	case SYS_FAN3:  	{sta = HAL_GPIO_ReadPin(SYS_FAN_CTL_3_GPIO_Port,SYS_FAN_CTL_3_Pin);				}break;
	case SYS_RUN_LED:  	{sta = !HAL_GPIO_ReadPin(SYS_RUN_LED_CTL_GPIO_Port,SYS_RUN_LED_CTL_Pin);		}break;
	case SYS_PWR_LED:  	{sta = !HAL_GPIO_ReadPin(SYS_POWER_LED_CTL_GPIO_Port,SYS_POWER_LED_CTL_Pin);	}break;
	case SOM_PWR_EN:  	{sta = HAL_GPIO_ReadPin(SOM_POWER_EN_GPIO_Port,SOM_POWER_EN_Pin);				}break;
	case SOM_DFU:  		{sta = !HAL_GPIO_ReadPin(SOM_FORCE_RECOVERY_GPIO_Port,SOM_FORCE_RECOVERY_Pin);	}break;
	case SOM_RESET:  	{sta = !HAL_GPIO_ReadPin(SOM_SYS_RESET_GPIO_Port,SOM_SYS_RESET_Pin);			}break;
	case SOM_SLEEP:  	{sta = !HAL_GPIO_ReadPin(SOM_SLEEP_WAKE_GPIO_Port,SOM_SLEEP_WAKE_Pin);			}break;
	case PMB_PS_ON:  	{sta = HAL_GPIO_ReadPin(PMB_PS_ON_GPIO_Port,PMB_PS_ON_Pin);						}break;
	default:			{log_e("PWR_Status device parameter is invalid.");							}break;
    }
    return sta;
}


