/************************************************************************/
/* Copyright 2016 MBARI													*/
/************************************************************************/
/* Summary  : Power Fail Handler for OASIS5 on PIC32MX470F512L			*/
/* Filename : pwrFail.c													*/
/* Author   : Robert Herlien (rah)										*/
/* Project  : OASIS Mooring Replacement (OASIS5)						*/
/* Revision : 1.0														*/
/* Created  : 08/26/2016												*/
/*                                                                          */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*                                                                          */
/************************************************************************/
/* Modification History:                                                */
/* 26aug2016 rah - created												*/
/************************************************************************/

#include <xc.h>
#include <oasis.h>						/* OASIS controller definitions	*/
#include <pwrFail.h>					/* This module					*/
#include <dig_io.h>						/* OASIS digital I/O definitions*/
#include <otask.h>						/* OASIS task routines			*/
#include <syslog.h>						/* System logger				*/
#include <picConfig.h>

#include <FreeRTOS.h>					/* FreeRTOS definitions			*/
#include <semphr.h>						/* FreeRTOS semaphore definitions*/


/********************************/
/*      External Data			*/
/********************************/

extern volatile UINT16  clkMs;			/* From timer.c					*/


/************************************************************************/
/* Function    : pwrFailInit											*/
/* Purpose     : Initialize this module									*/
/* Input       : None                                                   */
/* Outputs     : None													*/
/************************************************************************/
void pwrFailInit(void)
{
    INTCONCLR = _INTCON_INT0EP_MASK;    /* Interrupt on negative edge   */
    IPC0bits.INT0IP = 6;				/* PwrFail interrupt priority	*/
    IPC0bits.INT0IS = 3;

	IEC0SET = _IEC0_INT0IE_MASK;		/* Enable the interrupt			*/
	IFS0CLR = _IFS0_INT0IF_MASK;		/* Clear any pending interrupt	*/
    
} /* pwrFailInit() */


/************************************************************************/
/* Function	   : pwrFail												*/
/* Purpose	   : Function to shut down Oasis5 on power failure			*/
/* Inputs	   : None													*/
/* Outputs	   : None, Never exits										*/
/************************************************************************/
MLocal void pwrFail(void)
{
	UINT16	lastMs, relayMs, resetMs;

	pwrFailTaskPinOn();

	takeFileSem();
	sysLog("Power Fail!!");
	logFlush();
	setRtosRunMode(FALSE);
	vTaskSuspendAll();

	/* Turn off all relays.  Must do this here instead of calling	*/
	/* digPwrAllOff(), because we can't use OS for relay delay		*/
    dig12vEnable();
    relay1ResetOn();
    relay2ResetOn();
    relay3ResetOn();
    relay4ResetOn();

	lastMs = clkMs;
	relayMs = RELAY_DELAY_MS;
	resetMs = 2 * TICKS_PER_SEC;

	while(TRUE)
	{
		if (lastMs != clkMs)
		{
			lastMs = clkMs;
			if (relayMs)
				if (--relayMs == 0)
				{
					clearRelayCoils();
					dig12vDisable();
					pwrFailTaskPinOff();
				}
			if (--resetMs == 0)
			{
				sysLog("Power Fail Reset");
				picSoftReset();
			}
		}
	}

}


/************************************************************************/
/**********               ISR                                   *********/
/************************************************************************/

/************************************************************************/
/* Function    : _PwrFailInterrupt										*/
/* Purpose     : Power Fail Interrupt Handler							*/
/* Input       : None                                                   */
/* Comment     : Called from assembly language wrapper in port_asm.S    */
/************************************************************************/
void _PwrFailInterrupt(void)
{
	pwrFailIntPinOn();
	xTimerPendFunctionCallFromISR(pwrFail, NULL, 0, NULL);
	pwrFailIntPinOff();

	portYIELD();							/* Always dispatch the handler*/
	IFS0CLR = _IFS0_INT0IF_MASK;			/* Clear the interrupt		*/
}
