/****************************************************************************/
/* Copyright 2003-2012 MBARI												*/
/****************************************************************************/
/* Summary	: Event Cycle Routines for BEDS on Persistor CF2				*/
/* 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													*/
/* $Log$
 */
/****************************************************************************/

#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 <io.h>					/* BEDS I/O definitions					*/
#include <file.h>				/* BEDS file I/O definitions			*/
#include <variable.h>			/* Variable function definitions		*/
#include <dmpSetup.h>			/* BEDS DMP setup routines				*/
#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>

/* From Invensense MotionApps Stack */
#include "log.h"
#undef MPL_LOG_TAG
#define MPL_LOG_TAG "uMPL-main"

// MPL interface
#include "ml.h"
#include "mldl.h"
#include "mlFIFO.h"
#include "umpl-states.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;

	if (eventStruct.ppb == NULL)
		return;

	rcd.recType = PressureType;
	rcd.rsvd = 0;
	rcd.pressure = adcSampleAvg(EXT_PRESS_CHAN, 10);
	PPBWrite(eventStruct.ppb, &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;
	Nat16		pressTime=0;

	sensorsOn(SENSORS_SAMPLING);
	setupEventCycle();
	startTime = clkGetAccurateTime();

	while (inv_get_motion_state() == INV_MOTION)
	{
		if (newSecond())
		{
			checkVars();				/* Make sure variables are within limits */

			tod = clkGetAccurateTime();
			writeSecondMarker(eventStruct.ppb, tod);
			if ((tod - startTime) >= sensorWarmup)
				if (++pressTime >= evtPressureSecs)
				{
					writePressure();
					pressTime = 0;
				}

			checkDataFile(&eventStruct); /* See if it's time to write data*/

			if ((tod - startTime) > maxEvent)
			{									/* Exceeded max event time*/
				sysLog("Exceeded max event time");
				sensorsOff(SENSORS_SAMPLING);
				stopEventCycle();				/* Stop event			*/
				return(TMOUT);
			}
		}
		else
			ioSleep(loopDelay(evtFreq));

		/* MPU-6000 Interrupt
		 * In this sample app, we check the interrupt in the main loop.
		 * However, you can configure your microcontroller to trigger
		 * this interrupt asynchronously.
		 */
		if (ioCheckMPUInt()) {
			umplNotifyInterrupt(INTSRC_MPU);
		}

		/* umplOnTimer:
		 * This should be run either at a fixed rate corresponding to
		 * the FIFO Rate (see umpl-setup / inv_set_fifo_rate) or each time
		 * an MPU interrupt has occurred.
		 * It is a time-consuming call, so it is advised not to run it from
		 * an ISR.
		 */
#ifdef DEBUG_UMPL
		PIOSet(UMPL_ON_PIN);
		umplOnTimer();
		PIOClear(UMPL_ON_PIN);
#else
		umplOnTimer();
#endif
	}

	sensorsOff(SENSORS_SAMPLING);
	stopEventCycle();
	return(OK);
}
