//kernel.c

#include <912d60.h>
#include <stdio.h>
#include "kernel.h"


// GLOBAL VARIABLE DEFINITIONS
unsigned int current;		   	 		    // current task id number
unsigned long int system_tick;


// task control block
typedef struct task_block {
	 	unsigned char id; 			  		// ID of task
		enum task_state state;				// State
		unsigned char priority;				// Priority
	 	unsigned char *heap_ptr;			// heap addr while not current task
		unsigned int heap_size;				// heap size
		unsigned char *frame_ptr;			// CCR pointer
		};


// resource control block
typedef struct resource_block {
		unsigned char id;	   				// ID of resource
		enum resource_state state;			// State (busy, free...)
		unsigned char user;					// Current resource user/owner
		signed char queue[4];				// Tasks waiting on resource
		unsigned char queue_pos;			// Next free spot in queue
		};

		
struct task_block task[numtasks];
struct resource_block resource[numresources];



// FUNCTIONS

unsigned char get_task_id() { 
		 return task[current].id; 
}



unsigned char get_task_state(unsigned char id) { 

		 if (id > (numtasks-1)) {
	 	 	puts("kernel: illegal task id");
			return -1;
		 }
		 else
		 	 return task[id].state; 
}



unsigned char get_task_priority(unsigned char id) { 

		 if (id > (numtasks-1)) {
	 	 	puts("kernel: illegal task id");
			return -1;
		 }
	 	 else
		 	 return task[id].priority; 
}



int set_task_state(unsigned char id, unsigned char state) {

	// LOCAL VARIABLES
	char error_msg[35] = "kernel: illegal task state request";
	//INTR_OFF();
	
	if (id > (numtasks-1)) {
	   puts("kernel: illegal task id");
	   return -1;
	}
	if ((state > 4) || (state < 0)) {
	   puts(error_msg);
	   return -1;
	}
	if (state == running) {
	   puts(error_msg);
	   return -1;
	} 
	 
	switch (task[id].state) {
		   case idle:
				 if (state == idle)
				 	return 0;
				 if (state == pending) {
				 	task[id].state = pending;
					return 0;
				 }
				 else {
				 	  puts(error_msg);
					  return -1;
				 }
				 break;
		   case pending:
				if (state == pending)
				 	return 0;
				if (state == idle) {
				   task[id].state = idle;
				   return 0;
				}	
				else {
				   puts(error_msg);
				   return -1;
				}
				break;
		   case waiting:
		   		if (state == waiting)
				   return 0;
				else {
					 puts("kernel: unimplimented");
					 return -1;
				}
				break;
		   case finished:
		   		if (state == finished)
				   return 0;
				if (state == idle) {
				   task[id].state = idle;
				   return 0;
				}
				else if (state == pending) {
				   task[id].state = pending;
				   return 0;
				}
				else {
					 puts(error_msg);
					 return -1;
				}
				break;
		   default:
		   		   puts("kernel: unimplimented");
				   return -1;
				   break;
	 }
	 

	 //INTR_ON();
	 //return -1;
}



void set_task_priority(unsigned char id, unsigned char priority) {

	 if (priority == 0) priority = 1;
	 if (id > (numtasks-1))
	 	puts("kernel: illegal task id");
	 else if ((priority > 255) || (priority < 0))
	 	  puts("kernel: illegal priority");
	 else
	 	 task[id].priority=priority;
}

