/****************************************************************************/
/* Copyright 2012-2018 MBARI												*/
/****************************************************************************/
/* Summary	: Event Cycle Routines for BEDS2 on PIC32MX470					*/
/* Filename : event.c														*/
/* Author	: Robert Herlien (rah)											*/
/* Project	: BEDS (Benthic Event Detection System)							*/	
/* Revision : 1.0															*/
/* Created	: 11/28/2012													*/
/*																			*/
/* 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:													*/
/* 28nov2012 rah - created													*/
/* 23feb2018 rah - Ported to BEDS2 on PIC32MX470							*/
/****************************************************************************/

#include <mbariTypes.h>			/* MBARI type definitions				*/
#include <beds.h>				/* BEDS general definitions				*/		
#include <event.h>				/* BEDS event cycle						*/
#include <watch.h>				/* BEDS watch cycle						*/
#include <imu.h>				/* BEDS IMU routines					*/
#include <file.h>				/* BEDS file I/O definitions			*/
#include <variable.h>			/* Variable function definitions		*/
#include <clock.h>				/* BEDS Clock module					*/
#include <syslog.h>				/* System logger						*/
#include <adc.h>				/* BEDS Analog Module					*/

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct							/********************************/
{										/* Struct to accumulate pressure*/
	Nat32		accum;					/* accumulator					*/
	Nat16		nSamples;				/* number of samples accumulated*/
	Nat16		pressTime;				/* Time in seconds				*/
	MBool		warmedUp;				/* TRUE if sensor warmed up		*/
} PressureStruct;						/********************************/


/********************************/
/*		External Data			*/
/********************************/

Extern Int32	evtFreq;				/* FIFO rate during event		*/
Extern Int32	maxEvent;				/* Maximum time for event (secs)	*/
Extern Int32	sensorWarmup;			/* Warmup time for turning on system sensors*/
Extern Int32	evtPressureSecs;		/* Period (secs) to get press in event*/


/********************************/
/*		Module Local Data		*/
/********************************/

MLocal DataFileStruct eventStruct = 
	{"EVT", "EVENT.IDX", 1, 3000, 0, 0, 0};


/************************************************************************/
/* Function	   : eventInit												*/
/* Purpose	   : Initialize this module									*/
/* Inputs	   : None													*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
Errno eventInit(Void)
{
	eventStruct.fileIndex = 1;
	return(OK);
}


/************************************************************************/
/* Function	   : setupEventCycle										*/
/* Purpose	   : Set up to start an event cycle							*/
/* Inputs	   : None													*/
/* Outputs	   : None													*/
/************************************************************************/
MLocal Void setupEventCycle(Void)
{
	sysLog("Entering Event Cycle");

	serRxFlush(1);
	serRxFlush(2);
	sysLog("Entering Event Mode");

	imuSetup(evtFreq);
	eventStruct.dataRate = 60*evtFreq;
	eventStruct.maxVal = 0;
	openNewDataFile(&eventStruct);

	/* Read and throw away any samples still in queue.	Old samples		*/
	/* could be interpreted with old multipliers (before setDMP()		*/
	// umplOnTimer();
}


/************************************************************************/
/* Function	   : stopEventCycle											*/
/* Purpose	   : Tear down an event cycle								*/
/* Inputs	   : None													*/
/* Outputs	   : None													*/
/************************************************************************/
MLocal Void stopEventCycle(Void)
{
	closeDataFile(&eventStruct);
	sysLog("Exiting Event Cycle");
}


/************************************************************************/
/* Function	   : writePressure											*/
/* Purpose	   : Write a pressure record to event stream				*/
/* Inputs	   : None													*/
/* Outputs	   : None													*/
/************************************************************************/
MLocal Void writePressure(Void)
{
	PressureRcd rcd;

	rcd.recType = PressureType;
	rcd.rsvd = 0;
	rcd.pressure = adcSampleAvg(EXT_PRESS_CHAN, 10);
	writeDataFile(&eventStruct, &rcd, sizeof(rcd));
}


/************************************************************************/
/* Function	   : eventCycle												*/
/* Purpose	   : Run the event cycle for the BEDS application			*/
/* Inputs	   : None													*/
/* Outputs	   : OK, or TMOUT if exceeded maxEvent						*/
/************************************************************************/
Errno	eventCycle(Void)
{
	time_t		tod, startTime;
	Nat32		delay, pressTime=0;

	sensorsOn(SENSORS_SAMPLING);
	setupEventCycle();
	startTime = clkTime();

	while (imuGetMotionState() == IMU_MOTION)
	{
		while(imuReadFifo() > 0)
			recordDataPoint(&eventStruct);

		if (newSecond())
		{
			checkVars();				/* Make sure variables are within limits */

			tod = clkTime();
			writeSecondMarker(&eventStruct, tod);
			if ((tod - startTime) >= sensorWarmup)
				if (++pressTime >= evtPressureSecs)
				{
					writePressure();
					pressTime = 0;
				}

			if ((tod - startTime) > maxEvent)
			{									/* Exceeded max event time*/
				sysLog("Exceeded max event time");
				sensorsOff(SENSORS_SAMPLING);
				stopEventCycle();				/* Stop event			*/
				return(TMOUT);
			}
		}
		else
		{
			delay = loopDelay(evtFreq);
			if (delay >= TICKS_PER_SECOND)
				clkSleep(1);
			else
				clkIdle(delay);
		}
	}

	sensorsOff(SENSORS_SAMPLING);
	stopEventCycle();
	return(OK);
}
