#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_mixer.h>
#include <SDL/SDL_image.h>

#define ObjCNT 100

#define gNoid 16
#define iNoid 17
#define mNoid 18
#define tNoid 19
#define cNoid 20

#define console 10

#define eMOTION 5
#define ePRESS 6
#define eRELASE 7
#define eRESIZE 8
#define eREFOCUS 10
#define eFOCUS 11
#define eACTIVE 13
#define ePAUSE 12
#define eEXIT 15

  //click state
#define CLIK 1
#define DCLIK 2
#define RCLIK 3
#define CLIKD 4
#define CLIK4 45
  //event state
#define RELASE 16
#define MOTION 17
#define ACTIVE 2
#define EXIT 1
#define RESIZE 12
#define PRESS 15
/* 	default callback , place holder		 */
void NoidCallBackNULL(void) {}

/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @                                  NOID                                 @ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */

	int exitNOID;
/* ------------------------ SDL events-------------------------- */
SDL_Event etatNOID;
SDL_Color yellow = {255,255,0,255};

/* -------------------------- Object ---------------------------- */
	struct NoIdea{
		int layer;		void (*callback)(void);
		int timer,wait;		void (*timeback)(void);
		int event;		void (*evenback)(void);
		int click;		void (*clikback)(void);
		int over;		void (*overback)(void);
		int drop;		void (*dropback)(void);
		int jeton;		float x,y, z,r, h,v;
		char *carte;		int color,police;
	};
	struct NoIdea noid[ObjCNT];

	struct Lyer{
		int many;
		int active;		//active layer
		int running;		//running obj number
		int cntr[ObjCNT];
	};
	struct Lyer layer;

	struct sleep {
		int idle;
		int avr;
		int sum;
		int now;
	};
	struct sleep idle;

		char PerfNOID[30] = "IDLE";
    		char timNOID[30] = "TIMER";
    		char layNOID[30] = "LAYER";
/* ------------------------- File ------------------------------- */
	struct filling{	
		SDL_Surface *jeton[199];
		Mix_Music *ruban[3];
		TTF_Font *police;
	};
	struct filling fNOID;
/* ----------------------- Musique ------------------------------ */
Mix_Music *museNOID, *trackNOID;

/* -------------- main function callback -------------------------- */
void NoidCallBackNULL(void);
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */



/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/*                            Main Server                                    */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */

/* */

void NoidServerEXIT(void) {
	exitNOID = 1;
	}

void NoidServerPAUSE(void) {
	Uint8 pause = SDL_GetAppState();
	switch (pause) {
		//case !SDL_APPINPUTFOCUS:
		//break;
		case !SDL_APPACTIVE:
			noid[15].callback();
		break;
		//case !SDL_APPMOUSEFOCUS:
		//break;
	}
}

/* ==================================================================================================== */
/* ==================================================================================================== */
/* ==================================================================================================== */
void NoidCallBackMUSE(void) {
  //Mix_HaltMusic();
  //Mix_FreeMusic(museNOID);
  //museNOID= trackNOID;
  //Mix_PlayMusic(museNOID, 0);
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/* ==================================================================================================== */

void NoidServiceDROP(void) {	int cntr, lays;
	for (lays = 1; lays <= layer.many; lays = lays + 1) {
		cntr = layer.cntr[lays];
		if ((noid[cntr].drop != 0)&&((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active))) {

		}
	}
}

void NoidServiceOVER(void) {	int cntr, lays;
	for (lays = 1; lays <= layer.many; lays = lays + 1) {
		cntr = layer.cntr[lays];
		if ((noid[cntr].over != 0)&&((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active))) {
			if (	   (noid[eMOTION].x > (noid[cntr].x - (noid[cntr].h/2))) 
				&& (noid[eMOTION].x < (noid[cntr].x + (noid[cntr].h/2))) 
				&& (noid[eMOTION].y > (noid[cntr].y - (noid[cntr].v/2))) 
				&& (noid[eMOTION].y < (noid[cntr].y + (noid[cntr].v/2)))
				){	if (noid[cntr].overback != 0) {
						layer.running = cntr;
						noid[cntr].overback(); }
					cntr = ObjCNT;
				}
		}
	}
}

void NoidServiceROTOCURSOR(void) {
	if ((noid[eMOTION].x <= 1)&&(noid[eMOTION].x <= -1)&&(noid[eMOTION].y <= 1)&&(noid[eMOTION].y >= -1)) {
		noid[eMOTION].jeton = 1;
	}

	//noid[eMOTION].jeton = noid[eMOTION].jeton + 1;
	//if (noid[eMOTION].jeton >= 50) {
	//	noid[eMOTION].jeton = 41;
	//}
}

void NoidServiceCLIK(void) {	int cntr, lays;
	for (lays = 1; lays <= layer.many; lays = lays + 1) {
		cntr = layer.cntr[lays];
		if ((noid[cntr].click != 0)&&((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active))) {
			if ((noid[cntr].click == CLIK)
				&& (noid[ePRESS].x > (noid[cntr].x - (noid[cntr].h/2))) 
				&& (noid[ePRESS].x < (noid[cntr].x + (noid[cntr].h/2))) 
				&& (noid[ePRESS].y > (noid[cntr].y - (noid[cntr].v/2))) 
				&& (noid[ePRESS].y < (noid[cntr].y + (noid[cntr].v/2)))
				){
					if (noid[cntr].clikback != 0) {
						layer.running = cntr;
						noid[cntr].clikback(); }
					cntr = ObjCNT;				}
			if ((noid[cntr].click == DCLIK)
				&& (noid[ePRESS].x > (noid[cntr].x - (noid[cntr].h/2))) 
				&& (noid[ePRESS].x < (noid[cntr].x + (noid[cntr].h/2))) 
				&& (noid[ePRESS].y > (noid[cntr].y - (noid[cntr].v/2))) 
				&& (noid[ePRESS].y < (noid[cntr].y + (noid[cntr].v/2)))
				){	noid[cntr].click = CLIKD;
					noid[iNoid].timer = 400;
					cntr = ObjCNT;				}
			if ((noid[cntr].click == CLIKD)
				&& (noid[ePRESS].x > (noid[cntr].x - (noid[cntr].h/2))) 
				&& (noid[ePRESS].x < (noid[cntr].x + (noid[cntr].h/2))) 
				&& (noid[ePRESS].y > (noid[cntr].y - (noid[cntr].v/2))) 
				&& (noid[ePRESS].y < (noid[cntr].y + (noid[cntr].v/2)))
				){	if (noid[cntr].clikback != 0) {	
						layer.running = cntr;
						noid[cntr].clikback();}
					noid[iNoid].timer = 0;
					cntr = ObjCNT;				}
			if ((noid[cntr].click == 45)
				&& (noid[ePRESS].x > (noid[cntr].x - ((noid[cntr].h/2)*0.7071))) 
				&& (noid[ePRESS].x < (noid[cntr].x + ((noid[cntr].h/2)*0.7071))) 
				&& (noid[ePRESS].y > (noid[cntr].y - ((noid[cntr].v/2)*0.7071))) 
				&& (noid[ePRESS].y < (noid[cntr].y + ((noid[cntr].v/2)*0.7071)))
				){	if (noid[cntr].clikback != 0) {
						layer.running = cntr;
						noid[cntr].clikback();}
					cntr = ObjCNT;				}
		}
	}
}

void NoidServiceRECLIK(void) {	int cntr;
	for (cntr = 1 ; cntr < ObjCNT ; cntr = cntr + 1 ) 	{
		if ((noid[cntr].click != 0)&&((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active))) {
			if (noid[cntr].click == CLIKD) 
			{
				noid[cntr].click = DCLIK;
				noid[iNoid].timer = 0;
			}
		}
	}
}

/* ==================================================================================================== */
/* ==================================================================================================== */
/* ==================================================================================================== */


/* 	this server show all sprite contained in struct gNOID {} .
	this part get its sprite from SDL_surface fNOID.jeton[] array
	const char fNOID.carte define the array. it require SDL and
	SDL_rotozoom.h to work properly line 5 to 8 . if u feed
	Zoom and Roto of 0 , it will blit normally 				*/

void NoidServerBLIT(void) {	int cntr, lays;
		SDL_Rect	fenetre;
		SDL_Rect	cadre;
	if (noid[gNoid].z == 0) 
	{	noid[gNoid].z =1;	}
	noid[gNoid].h = fNOID.jeton[noid[layer.running].jeton]->w;
	noid[gNoid].v = fNOID.jeton[noid[layer.running].jeton]->h;
	float ratioNOID =  (float)fNOID.jeton[noid[gNoid].jeton]->h / fNOID.jeton[noid[gNoid].jeton]->w;
	for (lays = layer.many; lays >= 1; lays = lays - 1) {
		cntr = layer.cntr[lays];
		if (	(noid[cntr].jeton != 0)&&(noid[cntr].jeton != noid[gNoid].jeton)&&((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active)))
		{
			noid[cntr].h = ((float)fNOID.jeton[noid[cntr].jeton]->w / (fNOID.jeton[noid[layer.running].jeton]->w/2));
			noid[cntr].v = ((float)fNOID.jeton[noid[cntr].jeton]->h / (fNOID.jeton[noid[layer.running].jeton]->h/2));
			if (noid[cntr].z == 0) 
			{	noid[cntr].z =1;	}
				fenetre.x = ((noid[cntr].x * fNOID.jeton[noid[layer.running].jeton]->w) + (fNOID.jeton[noid[layer.running].jeton]->w) - (fNOID.jeton[noid[cntr].jeton]->w))/2;
				fenetre.y = ((-(noid[cntr].y) * fNOID.jeton[noid[layer.running].jeton]->h) + (fNOID.jeton[noid[layer.running].jeton]->h) - (fNOID.jeton[noid[cntr].jeton]->h))/2;
				fenetre.w = fNOID.jeton[noid[cntr].jeton]->w; 
				fenetre.h = fNOID.jeton[noid[cntr].jeton]->h; 
				cadre.x = 0; 
				cadre.y = 0;
				cadre.w = fNOID.jeton[noid[cntr].jeton]->w;
				cadre.h = fNOID.jeton[noid[cntr].jeton]->h;
				SDL_BlitSurface(fNOID.jeton[noid[cntr].jeton],&cadre,fNOID.jeton[noid[layer.running].jeton],&fenetre);
	    	}
	}
	SDL_UpdateRect(fNOID.jeton[noid[layer.running].jeton], 0, 0, 0, 0);
	//SDL_FillRect(fNOID.jeton[noid[layer.running].jeton],NULL,0);
}

void NoidServiceTXT(void) { int cntr, lays;
	/*this service switch jeton to a text output specified in */
	for (lays = layer.many; lays >= 1; lays = lays - 1) {
		cntr = layer.cntr[lays];
		if ((noid[cntr].jeton != 0)&&(noid[cntr].carte != 0))
		{
			//SDL_Color yellow = {255,255,0,255};
			if (fNOID.jeton[noid[cntr].jeton] != NULL) 
			{
				SDL_FreeSurface(fNOID.jeton[noid[cntr].jeton]);
			}
			fNOID.jeton[noid[cntr].jeton] = TTF_RenderText_Solid( fNOID.police , noid[cntr].carte, yellow);
		}
	}
}
/* ==================================================================================================== */
/* ========================================= Event Engine ============================================= */
/* ==================================================================================================== */
void NoidEventMOTION(void) {
	noid[eMOTION].x = ((float) etatNOID.motion.x / (noid[gNoid].h /2))-1;
	noid[eMOTION].y = ((float)noid[gNoid].v / noid[gNoid].v)-((float) etatNOID.motion.y / (noid[gNoid].v /2));
}
void NoidEventPRESS(void) {
	noid[ePRESS].x = ((float) etatNOID.button.x / (noid[gNoid].h /2))-1;
	noid[ePRESS].y = ((float)noid[gNoid].v / noid[gNoid].v)-((float) etatNOID.button.y / (noid[gNoid].v /2));
}
void NoidEventRELASE(void) {
	noid[eRELASE].x = ((float) etatNOID.button.x / (noid[gNoid].h /2))-1;
	noid[eRELASE].y = ((float)noid[gNoid].v / noid[gNoid].v)-((float) etatNOID.button.y / (noid[gNoid].v /2));
}


int pause;
void NoidEventMOUSEFOCUS(void) {

	if (((etatNOID.active.state == SDL_APPMOUSEFOCUS))&&(etatNOID.active.gain == 0))
	{
		//noid[eMOTION].jeton = 0;	
	}
	if ((etatNOID.active.gain != 0))
	{
		//noid[eMOTION].jeton = 1;	
	}
}





void NoidEventPAUSE(void) {
	if (((etatNOID.active.state == SDL_APPACTIVE) || (etatNOID.active.state == SDL_APPINPUTFOCUS))&&(etatNOID.active.gain == 0))
	{	
		if (layer.active != 99) {
			SDL_BlitSurface(fNOID.jeton[100],NULL,fNOID.jeton[99],NULL);
			noid[eACTIVE].jeton = 99;
			pause = layer.active;}
			layer.active = 99;
	}
}

void NoidEventUNPAUSE(void) {
				//GoTrance();
			noid[eACTIVE].jeton = 0;
			layer.active = pause;
}
/* ==================================================================================================== */
/* ======================================== Kernel Engine ============================================= */
/* ==================================================================================================== */
/*	Timer Counter and clock !!	*/

void NoidServerTIME(void) {
	}
	
/*	Real Time SERVER	*/

void NoidServerSCHED(void) {
	int temp = SDL_GetTicks();
	int cntr, down, lays;
	for (lays = 1; lays <= layer.many; lays = lays + 1) {
		cntr = layer.cntr[lays];
		if ((noid[cntr].timer != 0)&&((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active)))
		{	if (noid[cntr].wait == 0)
			{   noid[cntr].wait = temp + noid[cntr].timer;	}
			down = noid[cntr].wait - temp;
       		        if (temp > noid[cntr].wait)	
			{      	noid[cntr].wait = temp + noid[cntr].timer;
				idle.idle = 0;
				if (noid[cntr].timeback != 0) {
					layer.running = cntr;
       		            		noid[cntr].timeback();}
			} 
			else { if ( idle.idle > down  ) 
					{ idle.idle = down; }
			}
		} else {	noid[cntr].wait = 0;	}
        }
	idle.now = temp;
}

void NoidShowTIMER(void) {
       		sprintf(timNOID,"timer : %d ",idle.now);
		noid[2].carte = timNOID;
}

/*	IdleServer	*/


void NoidServerIDLE(void) {
	if (( idle.idle != 0))
	{
		idle.sum = idle.sum + idle.idle;

		SDL_Delay( idle.idle );
	}
	idle.idle = 30;
}

void NoidShowIDLE(void) {
       		sprintf(PerfNOID,"avr IDLE : %d msec",idle.avr);
		noid[1].carte = PerfNOID;
	idle.avr = idle.sum; idle.sum = 0;
}

/* 	interrupt server	*/

void NoidServerEVENT(void) {
        while ( SDL_PollEvent(&etatNOID) ) {
        	switch ( etatNOID.type ) {
                    case SDL_QUIT:
			noid[3].event = noid[3].event | (1 << ((EXIT)-1));
                        break;
		    case SDL_ACTIVEEVENT:
			noid[3].event = noid[3].event | (1 << (ACTIVE-1));
			break;
                    case SDL_KEYDOWN:
                        break;
                    case SDL_MOUSEMOTION:
			noid[3].event = noid[3].event | (1 << ((MOTION)-1));
	                break;
                    case SDL_MOUSEBUTTONDOWN:
			noid[3].event = noid[3].event | (1 << ((PRESS)-1));
	                break;
                    case SDL_MOUSEBUTTONUP:
			noid[3].event = noid[3].event | (1 << ((RELASE)-1));
	                break;
		    case SDL_VIDEORESIZE:
			noid[3].event = noid[3].event | (1 << ((RESIZE)-1));
			break;
			
                }
            }

	int lays;
	for (lays = 1; lays <= layer.many; lays = lays + 1) {
		int cntr = layer.cntr[lays];
		if ((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active)){
			if ((noid[3].event & (1 << (noid[cntr].event-1))) != 0) {
				if (noid[cntr].evenback != 0) {
					layer.running = cntr;
       		            		noid[cntr].evenback();}
			}
		}
	}
	noid[3].event = 0;
}

void NoidShowEVENT(void) {
	/* this apps will show an icon every time
	an event occure and will let the icon there for
	an 100 msec */
}

/*	layer server	*/

void NoidServerLAYER(void) {	int cntr;
	layer.many = 0;
	for (cntr = 1; cntr <= ObjCNT; cntr = cntr + 1) {
		if ((noid[cntr].layer == 0)||(noid[cntr].layer == layer.active)) {
			layer.many = layer.many + 1;
			layer.cntr[layer.many] = cntr;			
		} 
	}
}

void NoidShowLAYER(void) {
       		sprintf(layNOID,"%d active obj",layer.many);
		noid[4].carte = layNOID;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/* ==================================================================================================== */
void NoidServerINIT(){
	int cntr;

	printf("Loading 99 sprite !\n");
    char fileNOID[30];
    for (cntr=1;cntr <= 99;cntr = cntr+1) {
	SDL_Surface *takeNOID;
        sprintf(fileNOID,"./DataNOiD/noid%d.png",cntr);
	takeNOID = IMG_Load(fileNOID);
		if (takeNOID == NULL) {	
			printf("error loading : noid%d.png \n",cntr);
		}
	SDL_SetColorKey(takeNOID,SDL_RLEACCEL,0);
	fNOID.jeton[cntr] = SDL_DisplayFormatAlpha(takeNOID);
	SDL_SetColorKey(fNOID.jeton[cntr],SDL_RLEACCEL,0);
	SDL_FreeSurface(takeNOID);
    }

	printf("Loading music !\n");
   fNOID.ruban[1] =  Mix_LoadMUS("./DataNOiD/noidS1.ogg");
		if (fNOID.ruban[1] == NULL) {	
			printf("error loading : noidS%d.ogg \n",1);
		}
   museNOID = fNOID.ruban[1];
   Mix_PlayMusic(museNOID, 1);
   Mix_HookMusicFinished(NoidCallBackMUSE);

	printf("loading police\n");
   fNOID.police = TTF_OpenFont( "./DataNOiD/noidT1.ttf", 16 );
		if (fNOID.police == NULL) {	
			printf("error loading : noidT%d.ogg \n",1);
		}

	printf("prep noid layer \n");
	for (cntr = 1; cntr <= ObjCNT; cntr = cntr+1) {
		noid[cntr].layer = 2000000000;
	}

	noid[eEXIT].layer = 0; 
	noid[eEXIT].event = EXIT; 
	noid[eEXIT].evenback = &NoidServerEXIT;

	noid[eACTIVE].layer = 0; 
	noid[eACTIVE].event = ACTIVE; 
	noid[eACTIVE].evenback = &NoidEventPAUSE;

	noid[eFOCUS].layer = 0;
	noid[eFOCUS].event = ACTIVE; 
	noid[eFOCUS].evenback = &NoidEventMOUSEFOCUS;

	noid[ePAUSE].clikback = &NoidEventUNPAUSE; 
	noid[ePAUSE].layer = 99; 
	noid[ePAUSE].jeton = 11; 
	noid[ePAUSE].click = 1;
	noid[ePAUSE].x =0; 
	noid[ePAUSE].y =0;

	noid[eMOTION].layer = 0;	
	noid[eMOTION].event = MOTION;	
	noid[eMOTION].evenback = &NoidEventMOTION;
	noid[eMOTION].jeton = 1;

	noid[ePRESS].layer = 0;
	noid[ePRESS].event = PRESS;
	noid[ePRESS].evenback = &NoidEventPRESS;

	noid[eRELASE].layer = 0;
	noid[eRELASE].event = RELASE;
	noid[eRELASE].evenback = &NoidEventRELASE;

	noid[mNoid].layer = 0; 
	noid[mNoid].event = MOTION; 
	noid[mNoid].evenback = &NoidServiceOVER;
	//noid[mNoid].timer = 100;
	//noid[mNoid].timeback = &NoidServiceROTOCURSOR;

	noid[iNoid].layer = 0; 
	noid[iNoid].event = PRESS; 
	noid[iNoid].evenback = &NoidServiceCLIK; 
	noid[iNoid].timeback = &NoidServiceRECLIK;

	noid[gNoid].layer = 0; 
	noid[gNoid].timer = 30; 
	noid[gNoid].timeback = &NoidServerBLIT; 
	noid[gNoid].jeton = 100;
	noid[gNoid].z = 1;

	noid[tNoid].layer = 0;
	noid[tNoid].timer = 55;
	noid[tNoid].timeback = &NoidServiceTXT;

	noid[4].layer = 0;
	noid[4].callback = &NoidServerLAYER;
	noid[4].jeton = 29;
	noid[4].timeback = &NoidShowLAYER;
	noid[4].timer = 1000;
	noid[4].x = 0.4;
	noid[4].y = -0.8;
	noid[4].carte = layNOID;

	noid[3].layer = 0;
	noid[3].callback = &NoidServerEVENT;

	noid[2].layer = 0;
	noid[2].callback = &NoidServerSCHED;
	noid[2].jeton = 30;
	noid[2].timer = 100;
	noid[2].timeback = &NoidShowTIMER;
	noid[2].x = 0.4;
	noid[2].y = -0.7;
	noid[2].carte = timNOID;

	noid[1].layer = 0;
	noid[1].callback = &NoidServerIDLE;
	noid[1].timeback = &NoidShowIDLE;
	noid[1].timer = 1000;
   	noid[1].x = 0.4;
 	noid[1].y = -0.9;
 	noid[1].z = 1;
 	noid[1].r = 0;
	noid[1].jeton = 16;
	noid[1].carte = PerfNOID;

}

/* ==================================================================================================== */
/* ==================================================================================================== */
/* ==================================================================================================== */
void NoidServerLOOP(void) {
   while(!exitNOID)    {
	/* ------------------------------------------------------- */
	/* ---------------------> Layer <------------------------- */
	/* ------------------------------------------------------- */
		noid[4].callback();
	/* ------------------------------------------------------- */
	/* ---------------------> event <------------------------- */
	/* ------------------------------------------------------- */
		noid[3].callback();
	/* ------------------------------------------------------- */
	/* ---------------->  RT NOID  <-------------------------- */
	/* ------------------------------------------------------- */
		noid[2].callback();
	/* ------------------------------------------------------- */
	/* ---------------------> idle <-------------------------- */
	/* ------------------------------------------------------- */
		noid[1].callback();
	/* ------------------------------------------------------- */
	/* ----------------------> end loop <--------------------- */
	/* ------------------------------------------------------- */
    }
}

/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */
