;   ***************************************************************
;   * Copyright (C) 2010, Embed Inc (http://www.embedinc.com)     *
;   *                                                             *
;   * Permission to copy this file is granted as long as this     *
;   * copyright notice is included in its entirety at the         *
;   * beginning of the file, whether the file is copied in whole  *
;   * or in part and regardless of whether other information is   *
;   * added to the copy.                                          *
;   *                                                             *
;   * The contents of this file may be used in any way,           *
;   * commercial or otherwise.  This file is provided "as is",    *
;   * and Embed Inc makes no claims of suitability for a          *
;   * particular purpose nor assumes any liability resulting from *
;   * its use.                                                    *
;   ***************************************************************
;
;   Cooperative task manager.  The exported subroutines are:
;
;     TASK_INIT
;
;       Initializes the state.  Must be first call into this module.
;
;     TASK_NEW
;
;       Create a new task.  Call parameters:
;
;         W13  -  Size of the new task stack in bytes, must be even.
;
;         W14  -  Start address of the stack for the new task, must be even.
;
;       The new task starts immediately after the CALL TASK_NEW instruction.  It
;       is intended that a GOTO be put there.  The call returns 2 instruction
;       words after the call, skipping over the GOTO intended to be immediately
;       after the call.
;
;       Example call:
;
;         mov    #<stack size>, w13
;         mov    #<stack>, w14
;         call   task_new
;         goto   <new task start point>
;         ...             ;existing task continues here
;
;       The original task continues running until TASK_YIELD is called.
;
;     TASK_YIELD
;
;       Gives all other tasks a chance to run.  Registers listed in TSKSAVE are
;       preserved.
;
;       On a 33EP series dsPIC, the delay from the TASK_YIELD call in one task
;       to the first instruction in the next task is 25 cycles, plus two cycles
;       for every register saved.  When all register (W0-W14) are saved, a task
;       swap takes 55 cycles.  That is 786 ns at 70 MHz instruction rate.
;
;     TASK_YIELD_SAVE
;
;       Like TASK_YIELD, except that all registers are preserved.
;
;     TASK_TIME_DONE
;
;       Set Z if the current time slice has elapses, and clears Z otherwise.
;
;       This routine only exists when an external task yield time mechanism has
;       been implemented.  See the description of this mechanism in
;       QQQ_TASK.INS.DSPIC.
;
;     TASK_YIELD_IFTIME
;
;       Like TASK_YIELD except that the yield is only performed when there is an
;       external indication that it is time for the current task to yield.
;
;       This routine only exists when an external task yield time mechanism has
;       been implemented.  See the description of this mechanism in
;       QQQ_TASK.INS.DSPIC.
;
;     TASK_EXIT
;
;       Entry point to end the current task.  The task state slot becomes
;       unused, and may be re-used by a future call to TASK_NEW.  This entry
;       point can be CALLed, but will not return.  The stack state is
;       irrelevant on entry to TASK_EXIT.  The processor is reset on attempt
;       to exit the only task.
;
;     TASK_KILL
;
;       Kill the task with the ID in W0.  Nothing is done if the ID matches no
;       task.  If the current task is killed, this routine will not return.  The
;       processor is reset on attempt to kill the only task.
;
;     TASK_PRUNE
;
;       Delete all but the first W0 tasks in the list.  The processor is reset
;       on attempt to delete all tasks (W0 = 0).  If the task calling this
;       routine is not one of the first W0 tasks in the list, then not all
;       intended tasks may be deleted.
;
;       The purpose of this routine is to restore to a set of "base" tasks, with
;       all "new" tasks stopped.  To use this feature:
;
;         1  -  Create all the base tasks, and no others.
;
;         2  -  Call TASK_N_CURR to get the number of base tasks.
;
;         3  -  Create and possibly stop any number of new tasks.  However, the
;               original base tasks must not be stopped.
;
;         4  -  Call TASK_PRUNE with the number of tasks found in step 2.
;
;     TASK_N_MAX
;
;       Returns the maximum possible number of tasks in W0.
;
;     TASK_N_CURR
;
;       Returns the total number of current tasks in W0.
;
;     TASK_NID
;
;       Returns the task ID for the 0-N task slot identified in W0, where N is
;       the value returned by TASK_N_CURR minus 1.  The task ID is returned in
;       W0.
;
;       For valid task slot numbers, the Z flag is cleared.  For out of range
;       task slot numbers, the Z flag is set and the W0 value is undefined.
;
;     TASK_EXIST
;
;       Determine whether the task with ID in W0 exists.  Z is cleared if the
;       task exists and set otherwise.
;
;   Global state:
;
;     CURRTASK
;
;       Global 16 bit unsigned integer variable containing the ID of the
;       currently-running task.  This variable must be considered read-only by
;       application code.
;
;   This module is configured by the following preprocessor symbols and files:
;
;     MAXTASKS, integer
;
;       The maximum number of task that can simultaneously run.  Configuring for
;       more tasks takes more static storage.  Default = 4.
;
;     ENDLIM, integer
;
;       Minimum number of bytes available to a stack before the stack error trap
;       is taken.  A stack error trap is taken when a push leaves this many or
;       fewer bytes available to the stack.
;
;     QQQ_TASK.INS.DSPIC, include file
;
;       This include file sets configuration state that needs to be globally
;       known, and creates preprocessor routines that may be used outside the
;       TASK module.  See the header comments in this file for what options are
;       available and how they are customized.
;
;   The tasks are:
;
;     0  -  Original task.  This runs the main event loop after initialization.
;
;     1  -  *** fill in here ***
;
/include "qq2.ins.dspic"

;*******************************************************************************
;
;   Configuration constants.
;
/const   maxtasks integer = 4 ;maximum number of concurrent tasks supported
/const   endlim  integer = 6 ;stack err trap when push with this many bytes left on stack

/include "(cog)src/dspic/task.ins.dspic"
         .end