/* timeout.cpp -- Implement simple sample counter timeout mechanism
 * 					count out sample cycles then do something
 */
#include "timeout.h"	// get out extern defines

// RunTask state
word runState = rINIT;

/** start a sample count timeout but don't mess with runState
 *   used to count out sample cycles then do something
 *   while also checking other stati on each sample cycle
 *   outer RunTask exec function OR's iTIMEOUT into input state when done
 *  @param samples -- number of samples to wait, 2-254
 **/
word sTMOcnt = 0;	// sample counter, decr if non-zero
word nrState = 0;	// new run state to set after waiting, if non-zero
void startTMO( word samples )
{
	// add one count so we only do the check once in execTMO
	sTMOcnt = samples + 1;
	nrState = 0;	// default to do nothing
	return;
}

/** start a sample count timeout and set runState = rWAIT state
 *  when the TMO completes runState will be set to rState so we
 *  can continue from where-ever; used to passively wait for completion
 *  execTMO function also OR's iTIMEOUT into input state when done
 *  @param samples -- number of samples to wait, 2-65K
 *  @param rState -- new runState to set when samples expire
 **/
void startTMOwait( word samples, word rState )
{
	startTMO( samples );
	nrState = rState;	// non-default to do something when done
	runState = rWAIT;
}

/** cancel any impending timeout counter
 */
void stopTMO()
{
	sTMOcnt = 0;
	nrState = 0;
}

/** execute the sample count timeout
 *  check and decrement count on each call, once for each new input sample
 *  when the count expires and we have a new run state setting
 *   set runState = nrState so we can continue from whereever
 *  otherwise if we don't have a new run state just return iTIMEOUT
 *
 *  @return iTIMEOUT if we did timeout, or 0 if not
 **/
word execTMO(void)
{
	// decr our counter if we are using it
	// then check if it has expired and do stuff
	if( sTMOcnt != 0 )
	{
		if( --sTMOcnt == 1 )
		{
			sTMOcnt = 0;
			// if we have a new state, set it to clear rWAIT
			if( nrState != 0 )
			{
				runState = nrState;
				nrState = 0; // reset just in case we forget later
			}
			return iTIMEOUT;
		}
	}

	return 0;
}
