#include "stm32f4xx_hal.h"
#include "globals.h"
#include "wifi.h"


uint8_t gRemoteStillActive = 1;
uint8_t gGoToSleep = 0;


//GPIOA6 
// OK à 0
// KO à 1
void activateDetectionLossOfPower(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  GPIO_InitStruct.Pin = PW_KO_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // External Interrupt Mode with Rising edge trigger detection
  GPIO_InitStruct.Pull = GPIO_NOPULL; 
  HAL_GPIO_Init(PW_KO_GPIO_Port, &GPIO_InitStruct);	
//equiv	SYSCFG_EXTICR2 EXTI6 = 0000 (PA6)

	__HAL_GPIO_EXTI_CLEAR_IT(PW_KO_Pin);
	 
	HAL_NVIC_SetPriority(EXTI9_5_IRQn,0,0); // highest priority
	HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}

void disableDetectionLossOfPower(void)
{
	
  GPIO_InitTypeDef GPIO_InitStruct;

	EXTI->IMR &= ~PW_KO_Pin; // Mask EXTI6.  Necessaire ? Oui, car vecteur partagé
	
//	HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
	__HAL_GPIO_EXTI_CLEAR_IT(PW_KO_Pin);

  GPIO_InitStruct.Pin = PW_KO_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(PW_KO_GPIO_Port, &GPIO_InitStruct);	
	
}


// Always called with dma not running
void powerDownSequence(void)
{
	disableDetectionLossOfPower(); // Avoids the interrupt of detection of power loss
	// all pins at 0. Reset and Disabled WIFI, protects 244 buffers and WIFI module
	GPIOB->ODR = GPIOC->ODR = 0; // avoids driving the led buffers while they are not powered;
	GPIOA->ODR = PS_ON_Pin; // all at 0 except PS_ON
	powerDown();
	RunLedOff();
}

// PS_ON = PA7
// RST_ESP = PA8, force reset à 0
// EN_ESP = PA15 active à 1
// Always called with dma not running
void powerDownSequenceWifiActive(void)
{
	disableDetectionLossOfPower(); // Avoids the interrupt of detection of power loss
	// all pins at 0. Reset and Disabled WIFI, protects 244 buffers and WIFI module
	GPIOB->ODR = GPIOC->ODR = 0; // avoids driving the led buffers while they are not powered;
	GPIOA->ODR = (PS_ON_Pin)|(RST_ESP_Pin)|(EN_ESP_Pin); // all at 0 except PS_ON, RESET WIFI, ENABLE WIFI
	powerDown();
	RunLedOff();
}

// #define isPowerOK() (HAL_GPIO_ReadPin(PW_KO_GPIO_Port,PW_KO_Pin)==GPIO_PIN_RESET)


int powerUPSequence(void)
{
	  int i;

		powerUp();
	  for (i=0;i<50;i++)
		{
			myWait1ms(100);
			if (isPowerOK()) // up to 5 seconds...
			{
				activateDetectionLossOfPower();
				break;
			}
		}
		if (i<50)
		{
			RunLedOn();
			return 1;
		}
		powerDown();
		return 0;
}

// While running PA0 input toggle detected by EXTI0 mode
void PA0GPIOInputWithInterrupt(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

	HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); // inutile ??????
	HAL_NVIC_DisableIRQ(EXTI0_IRQn);
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // External Interrupt Mode with Rising edge trigger detection
  GPIO_InitStruct.Pull = GPIO_NOPULL; //PULLDOWN; // a terme : no pull
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* HAL_GPIO_Init is Supposed to do:
	SYSCFG->EXTICR[0] = 0; // Sel PA0 for EXTI0.
	EXTI->RTSR |= 0x00000001; // Rising Edge  USEFUL ??
	EXTI->PR = 0x01;
	EXTI->IMR |= 0x00000001; // Unmask EXTI0
*/
	HAL_NVIC_SetPriority(EXTI0_IRQn,10,0); // low priority
	HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

// 
void PA0GPIOInputNoInterrupt(void)
{
	EXTI->IMR &= ~GPIO_PIN_0; // Mask EXTI0.  Necessaire ? Redondant ???
	EXTI->PR = GPIO_PIN_0;
	HAL_NVIC_DisableIRQ(EXTI0_IRQn);
}

// Go To Standby, wait for wake up on rising edge on PA0/WAKEUPpin
// all pins become highz
/*
    *** Wake-up pin configuration ***
    ================================
    [..]
      (+) Wake-up pin is used to wake up the system from Standby mode. This pin is 
          forced in input pull-down configuration and is active on rising edges.
      (+) There is one Wake-up pin: Wake-up Pin 1 on PA.00.
	   (++) For STM32F446xx there are two Wake-Up pins: Pin1 on PA.00 and Pin2 on PC.13
           (++) For STM32F410xx there are three Wake-Up pins: Pin1 on PA.00, Pin2 on PC.00 and Pin3 on PC.01
*/

// Using PA0 in Standby WAKE UP mode from wait/stop mode to detect rising edge does not work, it re-starts immediately, even though the signal remains high (no rising edge).
// That's why I use STOP mode and exit with EXTI0 interrupt
	
void GoToStandby(void)
{

  PA0GPIOInputWithInterrupt();	
//	HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
//	HAL_PWR_EnterSTANDBYMode();
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);
	// because standby does not keep up the ram...the easy and safe thing to do is reset
	// exit reset by rising edge on PA0
//	HAL_PWR_EnterSTANDBYMode();
	NVIC_SystemReset();
	
}

extern TIM_HandleTypeDef htim3;

void remoteHALInit(void)
{
	// PA0GPIOInputWithInterrupt(); 
	// line ^ In comment : Let timer6 interrupt activate on first run; This way we avoid spurious off
	gRemoteStillActive = 1;
}

// Always called with  dma not running
uint8_t remoteManager(void)
{
	if (gGoToSleep==1)
	{
		powerDownSequence();
		GoToStandby();
	}
	// return from standby ? Never, we reboot
	return 1;
}

void waitNoRemote(void)
{
	float time;
	uint8_t lastRemotePin, remotePin;
	
	PA0GPIOInputNoInterrupt();
  // Si pas de toggle pendant 0.3sec, return
	time = getTime();
	
	while(1)
	{
		remotePin = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
		if (remotePin!=lastRemotePin)
		{
		   time = getTime();
		}
		else if (getTime()-time>0.3f)
		{
			return;
		}
		lastRemotePin = remotePin;
	}
}

// attente remote 433Mhz off puis on
// Always called with  dma not running
void goSleepWaitOffOn(void)
{
	powerDownSequence();
	waitNoRemote(); // si pas remote pendant 1sec
	GoToStandby(); // go real standby
}
