/*
 * @Description: 
 * @Date: 2021-03-10 10:49:52
 * @LastEditors: CK.Zh
 * @LastEditTime: 2021-03-10 11:57:47
 * @FilePath: \NaviKit_EC_stm32\App\Src\th_button.c
 */
#define LOG_TAG    "TH-Exti"

#include <th_exti.h>
#include "main.h"
#include "navikit.h"


//pressed time < short press time(ms)
#define SHORT_PRESS_TIME 		200

//pressed time > long press time(ms)
#define LONG_PRESS_TIME			1000

//define exti flag for task-notification / thread-flags
#define	THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_ACTIVE 	 	(0x01<< 0)
#define	THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_INACTIVE 	 	(0x01<< 1)
#define	THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_ACTIVE 	 	 	(0x01<< 2)
#define	THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_INACTIVE 	 	(0x01<< 3)
#define	THREAD_FLAG_EXTI_SERVICE_PWR_BTN_ACTIVE 	 		(0x01<< 4)
#define	THREAD_FLAG_EXTI_SERVICE_PWR_BTN_INACTIVE 	 	 	(0x01<< 5)
#define	THREAD_FLAG_EXTI_SERVICE_CUS_BTN_ACTIVE 	 		(0x01<< 6)
#define	THREAD_FLAG_EXTI_SERVICE_CUS_BTN_INACTIVE 	 	 	(0x01<< 7)


//Thread
const osThreadAttr_t ExtiServiceTask_attributes = {
  .name = "ExtiServiceTask",
  .priority = (osPriority_t) osPriorityBelowNormal1,
  .stack_size = 256 * 4
};

//Timer
const osTimerAttr_t PwrBtnLongPressTimer_attributes = {
  .name = "PwrBtnLongPressTimer"
};
const osTimerAttr_t CustBtnLongPressTimer_attributes = {
  .name = "CustBtnLongPressTimer"
};
const osTimerAttr_t PwrBtnShortPressTimer_attributes = {
  .name = "PwrBtnShortPressTimer"
};
const osTimerAttr_t CustBtnShortPressTimer_attributes = {
  .name = "CustBtnShortPressTimer"
};

// //Event Flag
// const osEventFlagsAttr_t ExtiEventFlags_attributes = {
//   .name = "ExtiEventFlags"
// };


/* USER CODE BEGIN Header_ExtiServiceTask */
/**
* @brief Function implementing the ExtiServiceTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_ExtiServiceTask */
void ExtiServiceTask(void *argument)
{
  /* USER CODE BEGIN ExtiServiceTask */
  /* Infinite loop */
	uint32_t thread_flag = 0;
	log_d("Start EXTI Service Task");

	if(HAL_GPIO_ReadPin(SYS_POWER_BTN_GPIO_Port, SYS_POWER_BTN_Pin)==GPIO_PIN_SET)
		osTimerStart(PwrBtnLongPressTimerHandle,LONG_PRESS_TIME);

  for(;;)
  {
	  thread_flag = osThreadFlagsGet();
	  //shutdown request pin
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_ACTIVE){
		  log_i("SOM's shutdown_req pin falling edge, SOM request to shutdown.");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_ACTIVE);
	  }
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_INACTIVE){
		  log_v("SOM's shutdown_req pin rising edge");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_INACTIVE);
	  }

	  //module sleep pin
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_ACTIVE){
		  log_v("SOM's mod_sleep pin rising edge");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_ACTIVE);
	  }
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_INACTIVE){
		  log_v("SOM's mod_sleep pin falling edge");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_INACTIVE);
	  }

	  //power button pin
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_PWR_BTN_ACTIVE){
		  log_v("power_btn status: pressed.");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_PWR_BTN_ACTIVE);
		  if(!osTimerIsRunning(PwrBtnLongPressTimerHandle)){
				osTimerStart(PwrBtnLongPressTimerHandle,LONG_PRESS_TIME);
				osTimerStart(PwrBtnShortPressTimerHandle,SHORT_PRESS_TIME);
		  }
	  }
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_PWR_BTN_INACTIVE){
		  log_v("power_btn status: released.");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_PWR_BTN_INACTIVE);
			osTimerStop(PwrBtnLongPressTimerHandle);
			osTimerStop(PwrBtnShortPressTimerHandle);
	  }

	  //custom button pin
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_CUS_BTN_ACTIVE){
		  log_v("custom_btn status: pressed.");
		  osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_CUS_BTN_ACTIVE);
		  if(!osTimerIsRunning(CustBtnLongPressTimerHandle)) {
				osTimerStart(CustBtnLongPressTimerHandle,LONG_PRESS_TIME);
				osTimerStart(CustBtnShortPressTimerHandle,SHORT_PRESS_TIME);
		  }
	  }
	  if(thread_flag & THREAD_FLAG_EXTI_SERVICE_CUS_BTN_INACTIVE){
			log_v("custom_btn status: released.");
			osThreadFlagsClear(THREAD_FLAG_EXTI_SERVICE_CUS_BTN_INACTIVE);
			osTimerStop(CustBtnLongPressTimerHandle);
			osTimerStop(CustBtnShortPressTimerHandle);
	  }

	  osDelay(10);

  }
  /* USER CODE END ExtiServiceTask */
}




void PwrBtnLongPressTimerCallback(void *argument)
{
  log_v("power button long pressed.");
    switch(NaviKit.sys.sta){
      case run:  {NaviKit.sys.next_sta = idle;log_v("change to idle");      }break;//system is run now, user request to idle
      case idle: {NaviKit.sys.next_sta = run;log_v("change to run");      }break;//system is idle now , user request to power on
      case dfu:  {NaviKit.sys.next_sta = idle;log_v("change to idle");      }break;
      case sleep:{NaviKit.sys.next_sta = run;log_v("change to run");      }break;
      case isp:  {NaviKit.sys.next_sta = idle;log_v("change to idle");      }break;
      default : break;
    }
}
void CustBtnLongPressTimerCallback(void *argument)
{
  log_v("custom button long pressed.");
    switch(NaviKit.sys.sta){
      case run:{//system is run now, user request to reboot SOM
    	  som_reboot(100);
      }break;
      case idle:{
      }break;
      case dfu:{
    	  som_reboot(100);
      }break;
      case sleep:{
      }break;
      default : break;
    }
}
void PwrBtnShortPressTimerCallback(void *argument)
{
//  if(osThreadFlagsGet() & THREAD_FLAG_EXTI_SERVICE_PWR_BTN_INACTIVE){//power_button has released
	log_v("power button short pressed.");
	switch(NaviKit.sys.sta){
	  case run:  {//som is running, send sleep requeset to operate system
		  log_v("Request operate system pop up the shutdown dialog.");
		  PWR_Enable(SOM_SLEEP,true,100);
		  PWR_Enable(SOM_SLEEP,false,0);
	  }break;
	  case idle: {     }break;//system is idle now , user request to power on
	  case dfu:  {      }break;
	  case sleep:{     }break;
	  case isp:  {       }break;
	  default : break;
	}
//  }
}
void CustBtnShortPressTimerCallback(void *argument)
{
//	if(osThreadFlagsGet() & THREAD_FLAG_EXTI_SERVICE_PWR_BTN_INACTIVE){//power_button has released
	  log_v("custom button short pressed.");
		switch(NaviKit.sys.sta){
		  case run:{
		  }break;
		  case idle:{
		  }break;
		  case dfu:{
		  }break;
		  case sleep:{
		  }break;
		  default : break;
		}
//	}
}



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch (GPIO_Pin){
		case SOM_SHUTDOWN_REQ_Pin:{
			if(HAL_GPIO_ReadPin(SOM_SHUTDOWN_REQ_GPIO_Port, SOM_SHUTDOWN_REQ_Pin)==GPIO_PIN_RESET){//falling edge trigger
				  if(NaviKit.sys.sta == run){//if jetson nano shutdown output low,the power_en should be set low less than 10us
						PWR_Enable_IRQ(SOM_PWR_EN,false,0);
						NaviKit.sys.next_sta = idle;
						osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_ACTIVE);
				  }
			}else{//Rising edge trigger
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_SHUTDOWN_REQ_INACTIVE);
				}
		}break;

		case SOM_MOD_SLEEP_Pin:{
			if(HAL_GPIO_ReadPin(SOM_MOD_SLEEP_GPIO_Port, SOM_MOD_SLEEP_Pin)==GPIO_PIN_SET){//Rising edge trigger
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_ACTIVE);
			}else{//falling edge trigger
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_MOD_SLEEP_INACTIVE);
			}
		}break;
		case SYS_POWER_BTN_Pin:{
			if(HAL_GPIO_ReadPin(SYS_POWER_BTN_GPIO_Port, SYS_POWER_BTN_Pin)==GPIO_PIN_SET){//Rising edge trigger
//				NaviKit.sys.power_btn = true;
				//power button pressed
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_PWR_BTN_ACTIVE);
			}else{//falling edge trigger
//				NaviKit.sys.power_btn = false;
				//power button released
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_PWR_BTN_INACTIVE);
			}
		}break;
		case SYS_CUSTOM_BTN_Pin:{
			if(HAL_GPIO_ReadPin(SYS_CUSTOM_BTN_GPIO_Port, SYS_CUSTOM_BTN_Pin)==GPIO_PIN_RESET){//falling edge trigger
//				NaviKit.sys.custom_btn = true;
				//custom button pressed
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_CUS_BTN_ACTIVE);
			}else{//Rising edge trigger
//				NaviKit.sys.custom_btn = false;
				//custom button released
				osThreadFlagsSet(ExtiServiceTaskHandle,THREAD_FLAG_EXTI_SERVICE_CUS_BTN_INACTIVE);
			}
		}break;
	}

}

