#include <krnl.h>

// state dft
// just using krnl for showing how to intergrate RT OS ...


enum states {INIT,CONTROLNORM,CONTROLALERT};


// state functions

k_t * resetSem, *periodeSem, *alertSem;


enum states controlNorm(void)
{
	// good idea or not  - I will clean bef entering this state 
	k_clear_sem(alertSem); // entry clear intr signal alertSem for old interrupts/signals
	
	//k_set_sem_timer(periodeSem,6);  // just my sampleFreq
	
	while (1) {
		// resetSignal
		if (0 <= k_wait(alertSem,-1)) {
			// handle signal
			return CONTROLALERT;  // Leaving
		}

		k_wait(periodeSem,0);
		// otherwise control code repetetive
	}
}

/*
 *  controlAlert state
 * signal to resetSem will be lost if the task is NOT in CONTROLALERT state
 * accc to what it should be
 * 
 * The task has one semaphore for periodic running
 * k_set_sem_timer reset value to 0 and set timer to the new periode time (10)
 */

enum states controlAlert(void)
{
	// good idea or not - k_clear_sem(resetSem); // entry clear intr signal alertSem for old interrupts
	
	// k_set_sem_timer(periodeSem,10);  // just my sampleFreq
	
	while (1) {
		// resetSignal ?
		if (k_wait(resetSem,-1)) {  // return 1: if got a signal without  waiting
			// handle signal        //        0: if received a signal but has been waiting on it
			                        //        -1: timeout without receiving a signal , or just no 
			                        // signel if I do not want to wait (call with timeout -1)
	
			return CONTROLNORM;  // Leaving 
		}

		k_wait(periodeSem,0);
		// otherwise alert code on periodic manner
	}
}


enum states controlInit(void)
{
	k_sem_timer(periodeSem,10); // sampling sampleFreq
	// init whatever you need
 	return CONTROLNORM; // return next state
}


k_t * controlT;
#define CONTROLSTAK 150
char controlStk[CONTROLSTAK];

void controlTask()
{
	static enum states state;
	
   state = controlInit();

	while (1) {
		switch (state) {
			case INIT:
				state = init();
				break;
			case CONTROLNORM:
				state = controlNorm();
				break;
			case CONTROLALERT:
				state = controlAlert();
				break;
			default:
				state = INIT;
		}
	}
}

void setup()
{
	k_init(1,2,0);
	resetSem = k_crt_sem(0,1); // only need one pending signal
	alertSem = k_crt_sem(0,1); // only need one pending signal
	
	periodeSem = k_crt_sem(0,2); // only need one pending signal
    
	controlT = k_crt_task(controlTask,10,controlStk,CONTROLSTAK);	
	k_start();
}

void loop() {}
/**
 * case-switch considerations
 * Finding of the proper case can be carried out 
 * in two ways.
 * 
 * 1) if (..) else if (..) ..
 * So if you do have 100 case then in average you 
 * will do 50 if (...)
 * 
 * 2) if you order your cases in numerical order like
 * case 0:
 * ...
 * break;
 * case 1: 
 * ...
 * break;
 * and so forth
 * a jump table will be generated you just jump to the right case entry.
 * so no performance lack even in a case with several 100 entries.
 * 
 * By using the enum state above we are guaranteed the states are numbered 0,1,2,..
 * Then you just need to code our case switch in numerical order. 
 * 
 */
