//*****************************************************************************
// TaskManager
// Version 2.0 Fev 2005
//
// 2.0 -> -Re work all the interrupt code
// 1.0 -> -Everything is new
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//                T I M E R   U S A G E
//
// Timer 0 is use by Task Manager
//
//*****************************************************************************
//
//*****************************************************************************
//                      I N C L U D E
//*****************************************************************************
#include <iom32v.h>
#include <shortnametype.h>
#include <macros.h>
#include <stdlib.h>
#include <STRING.H>
#include "TaskManager.h"
//#define MINIMUM_CODE    // if def save 71 words of code but no more
                          // checking of Register and UnRegister

//*****************************************************************************
//            G L O B A L   V A R I A B L E
//*****************************************************************************
typedef struct Task
{
  void (*FunctionPTR)(void);
  uint Interval;
  uint Ticker;
  ushort Persiste;
}Task;
Task TaskList[MAX_TASK];
Task TaskAdd;
Task TaskDel;
int TaskMax = 0;

/******************************************************************************

Name:         void TaskInit(void)

Description:  Init task system

Input:        none

Output:       none

Misc:         Use Timer 0

******************************************************************************/
void TaskInit(void)
{
  //Timer0
  TCCR0 = 0x02;               // Timer0 / 8
  TIMSK |= (1<<TOIE0);        // int enable on Timer 0 overflow
}

/******************************************************************************

Name:         int TaskRegister( void(*FunctionPTR)(void),
                                int Interval,
                                ushort Persiste)

Description:  Register a function to be call

Input:        void  Function pointer
              int   Interval
              uchar Persiste

Output:       0 -> Task not registrated (error)
              1 -> Task is now registrated

Misc:

******************************************************************************/
int TaskRegister(void(*FunctionPTR)(void),
                 uint Interval,
                 ushort Persiste)
{
  #ifndef MINIMUM_CODE
  uint i = 0;

  if (FunctionPTR == NULL) return 0;
  if (TaskMax >= MAX_TASK) return 0;

  while (TaskAdd.FunctionPTR != NULL)
  {
    WDR();
    if (i++ > 65530) return 0;
  }
  #endif
  TaskAdd.FunctionPTR = FunctionPTR;
  TaskAdd.Interval = Interval;
  TaskAdd.Persiste = Persiste;
  return 1;
}

/******************************************************************************

Name:         int TaskUnRegister(void(*FunctionPTR)(void))

Description:  UnRegister a function

Input:        Function pointer

Output:       0 -> Task not find
              1 -> Task is unregistrated

Misc:

******************************************************************************/
int TaskUnRegister(void(*FunctionPTR)(void))
{
  #ifndef MINIMUM_CODE
  uint i = 0;

  if (FunctionPTR == NULL) return 0;

  while(TaskDel.FunctionPTR != NULL)
  {
    WDR();
    if (i++ > 65530) return 0;
  }
  #endif
  TaskDel.FunctionPTR = FunctionPTR;
  return 1;
}

/**********************************************************

Name:         int TaskCheckRegister(void(*FunctionPTR)(void))

Description:  Check if a function is register

Input:        Function pointer

Output:       0 -> Not register
              1 -> Register

Misc:

**********************************************************/
int TaskCheckRegister(void(*FunctionPTR)(void))
{
  ushort i;

  for (i=0; i < TaskMax; i++)
  {
    if (TaskList[i].FunctionPTR == FunctionPTR) return 1;
  }
  return 0;
}

/**********************************************************

Name:         void TaskBlock(int Time)

Description:  Block for x time

Input:        none

Output:       none

Misc:

**********************************************************/
void TaskBlock(uint Time)
{
  TaskRegister(TaskDummy,Time,FALSE);
  while (TaskCheckRegister(TaskDummy)) WDR();
}

void TaskDummy(void)
{
}

/**********************************************************

Name:         void TaskStop(void)

Description:  Stop Task Execution

Input:        none

Output:       none

Misc:

**********************************************************/
void TaskStop(void)
{
  TIMSK &= ~(1<<TOIE0);   // int disable on Timer 0 overflow
}

/**********************************************************

Name:         void TaskStart(void)

Description:  Start Task Execution

Input:        none

Output:       none

Misc:

**********************************************************/
void TaskStart(void)
{
  TIMSK |= (1<<TOIE0);    // int enable on Timer 0 overflow
}

/**********************************************************

Name:         void TaskExecute(void)

Description:  TaskExecute

Input:        none

Output:       none

Misc:         TaskExecute is execute each 100us

**********************************************************/
#pragma interrupt_handler TaskExecute:12
void TaskExecute(void)
{
  static ushort i,j;
  static void (*FunctionPTR)(void);

  TCNT0 = 255 - (XTAL / 8 / 10000);
  TaskStop();
  WDR();

  if (TaskDel.FunctionPTR != NULL) _TaskUnRegister();
  if (TaskAdd.FunctionPTR != NULL) _TaskRegister();
  
  for (i=0;i<TaskMax;i++)
  {
    if (TaskList[i].Ticker++ >= TaskList[i].Interval) 
    {
      FunctionPTR = TaskList[i].FunctionPTR;
      if (!TaskList[i].Persiste)
      {
        for (j=i;j<TaskMax;j++) memcpy(&TaskList[j],&TaskList[j+1],sizeof(Task));
        TaskMax--;
      }
      else
      {
        TaskList[i].Ticker = 0;
      }
      SEI();
      FunctionPTR();
      CLI();
    }
  }
  TaskStart();
}

/******************************************************************************

Name:         void _TaskUnRegister(void)

Description:  UnRegister a function

Input:        TaskDel struct

Output:       none

Misc:

******************************************************************************/
void _TaskUnRegister(void)
{
  ushort i,j;

  for (i=0;i<TaskMax;i++)
  {
    if (TaskList[i].FunctionPTR == TaskDel.FunctionPTR)
    {
      for (j=i;j<TaskMax;j++) memcpy(&TaskList[j],&TaskList[j+1],sizeof(Task));
      TaskMax--;
      TaskDel.FunctionPTR = NULL;
      return;
    }
  }
  TaskDel.FunctionPTR = NULL;
}

/******************************************************************************

Name:         int _TaskRegister(void)

Description:  Register a function

Input:        TaskAdd struct

Output:       none

Misc:

******************************************************************************/
void _TaskRegister(void)
{
  TaskList[TaskMax].FunctionPTR = TaskAdd.FunctionPTR;
  TaskList[TaskMax].Interval = TaskAdd.Interval;
  TaskList[TaskMax].Ticker = 0;
  TaskList[TaskMax].Persiste = TaskAdd.Persiste;
  TaskAdd.FunctionPTR = NULL;
  TaskMax++;
}
