//////////////////////////////////////////////////////////////////////////////
// Filename:          C:\School\Project\MPSoC\Multiprocs/drivers/task_controller_if_v1_00_a/src/task_controller_if.c
// Version:           1.00.a
// Description:       task_controller_if Driver Source File
// Date:              Sat Apr 18 16:21:40 2009 (by Create and Import Peripheral Wizard)
//////////////////////////////////////////////////////////////////////////////

#define START_EXECUTE_FLAG 0x0080
#define PROC_DONE_FLAG 0x0040
#define EXECUTING_FLAG 0x4000
#define START_TASK_CONTROL_FLAG 0x8000
#define ALL_PROCS_DONE 0x0020

/***************************** Include Files *******************************/

#include "task_controller_if.h"

/************************** Function Definitions ***************************/


/******
This function continuously checks the status from the task controller until there
is either a new task to execute or all tasks have been finished.

The number of the task that can execute is returned, or the TASKS_DONE_FLAG if
all tasks are finished.
*****/
Xuint16 wait_for_next_task(Xuint32 baseaddr)
{
	Xuint16 status;
	Xuint16 retVal;
	
	status = TASK_CONTROLLER_IF_mReadSlaveReg2(baseaddr);
	
	//wait until either the task controller signals that a new task can be executed,
	//or that all of this processor's task are complete
	while (((status & START_EXECUTE_FLAG) == 0) && ((status & PROC_DONE_FLAG) == 0)) 
	{
		status = TASK_CONTROLLER_IF_mReadSlaveReg2(baseaddr);		
	}
	
	//if the processor is done executing all tasks
	if ((status & PROC_DONE_FLAG) == PROC_DONE_FLAG)
	{
		retVal = TASKS_DONE_FLAG;
	}
	else
	{	
		//only 8 bits of the task number are valid
		retVal = (0xFF00 & TASK_CONTROLLER_IF_mReadSlaveReg1(baseaddr)) >> 8;
	}
	
	return retVal;
}

/******
This function sets the "executing" signal to high if the parameter is non-zero, or 
low if the parameter is 0.  When the "executing" signal is high the task controller
knows that the processor is executing a task.  When the signal is low the processor
is idle.
*****/
void set_executing_flag(Xuint32 baseaddr, Xuint8 execute)
{
	Xuint16 status;
	
	//first read the status so we can set all other bits back to the same value, so only the 
	// the executing flag is changed
	status = TASK_CONTROLLER_IF_mReadSlaveReg2(baseaddr);
	
	if (execute == 0)
	{
	   //change execute flag bit to 0
		status = status & (!EXECUTING_FLAG);	
	}
	else
	{
	   //change execute flag bit to 1
		status = status | EXECUTING_FLAG;
	}
	
	//write status back, with updated execute flag
	TASK_CONTROLLER_IF_mWriteSlaveReg2(baseaddr, status);	
}

/******
This function sets the "start_task_control" signal to low if the parameter is non-zero, or 
high if the parameter is 0.  When the "start_task_control" signal is low the task controller
will start performing the task scheduling.  This function will only do something for the 
master processor.  For all other processors the start_task_control signal will not be connected
to the task controller, and therefore it will do nothing.
*****/
void set_start_task_control_flag(Xuint32 baseaddr, Xuint8 start_task_control)
{
	Xuint16 status;
	
	//first read the status so we can set all other bits back to the same value, so only the 
	// the start_task_control flag is changed
	status = ALL_PROCS_DONE;
	
	if (start_task_control == 0)
	{
	   //change start_task_control flag bit to 1, which disables task control
		status = status | START_TASK_CONTROL_FLAG;
	}
	else
	{
		//change start_task_control flag bit to 0, which enables task control
		status = status & (!START_TASK_CONTROL_FLAG);		   
	}
	
	//write status back, with updated start_task_control flag
	TASK_CONTROLLER_IF_mWriteSlaveReg2(baseaddr, status);	
}

/******
This function returns the iteration number.  The iteration number specifies
how many times the currently requested task has previously been executed. 
*****/
Xuint16 get_current_iteration(Xuint32 baseaddr)
{
	return (TASK_CONTROLLER_IF_mReadSlaveReg0(baseaddr));
}

/******
This function returns 0 if not all processors are done executing, and 1 if all
tasks are done executing. 
*****/
Xuint8 all_tasks_done(Xuint32 baseaddr)
{
	Xuint8 retVal;
	
	if ((TASK_CONTROLLER_IF_mReadSlaveReg2(baseaddr) & ALL_PROCS_DONE) == 0)
	{
		retVal = 0;
	}
	else
	{
		retVal = 1;
	}
	return retVal;
}

void init_task_controller(Xuint32 baseaddr)
{
	TASK_CONTROLLER_IF_mReset(baseaddr);
}
