+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need\r
+ * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.\r
+ *\r
+ * \deprecated This module is deprecated and will be removed in a future library release.\r
+ */\r
+ \r
+/** @defgroup Group_Scheduler Simple Task Scheduler - LUFA/Scheduler/Scheduler.h\r
+ *\r
+ * \deprecated This module is deprecated and will be removed in a future library release.\r
+ *\r
+ * \section Sec_Dependencies Module Source Dependencies\r
+ * The following files must be built with any user project that uses this module:\r
+ * - LUFA/Scheduler/Scheduler.c\r
+ *\r
+ * \section Module Description\r
+ * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need\r
+ * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.\r
+ *\r
+ * For a task to yield it must return, thus each task should have persistent data marked with the static attribute.\r
+ *\r
+ * Usage Example:\r
+ * \code\r
+ * #include <LUFA/Scheduler/Scheduler.h>\r
+ * \r
+ * TASK(MyTask1);\r
+ * TASK(MyTask2);\r
+ * \r
+ * TASK_LIST\r
+ * {\r
+ * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },\r
+ * { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1 },\r
+ * }\r
+ *\r
+ * int main(void)\r
+ * {\r
+ * Scheduler_Start();\r
+ * }\r
+ *\r
+ * TASK(MyTask1)\r
+ * {\r
+ * // Implementation Here\r
+ * }\r
+ *\r
+ * TASK(MyTask2)\r
+ * {\r
+ * // Implementation Here\r
+ * }\r
+ * \endcode\r
+ *\r
+ * @{\r
+ */\r
+ \r
+#ifndef __SCHEDULER_H__\r
+#define __SCHEDULER_H__\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <stdbool.h>\r
+ \r
+ #include <util/atomic.h>\r
+\r
+ #include "../Common/Common.h"\r
+\r
+ /* Enable C linkage for C++ Compilers: */\r
+ #if defined(__cplusplus)\r
+ extern "C" {\r
+ #endif\r
+\r
+ /* Public Interface - May be used in end-application: */\r
+ /* Macros: */\r
+ /** Creates a new scheduler task body or prototype. Should be used in the form:\r
+ * \code\r
+ * TASK(TaskName); // Prototype\r
+ *\r
+ * TASK(TaskName)\r
+ * {\r
+ * // Task body\r
+ * }\r
+ * \endcode\r
+ */\r
+ #define TASK(name) void name (void)\r
+ \r
+ /** Defines a task list array, containing one or more task entries of the type TaskEntry_t. Each task list\r
+ * should be encased in curly braces and ended with a comma.\r
+ *\r
+ * Usage Example:\r
+ * \code\r
+ * TASK_LIST\r
+ * {\r
+ * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },\r
+ * // More task entries here\r
+ * }\r
+ * \endcode\r
+ */\r
+ #define TASK_LIST TaskEntry_t Scheduler_TaskList[] = \r
+ \r
+ /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type\r
+ * SchedulerDelayCounter_t.\r
+ */\r
+ #define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1)\r
+\r
+ /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */\r
+ #define TASK_RUN true\r
+\r
+ /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */\r
+ #define TASK_STOP false\r
+ \r
+ /* Pseudo-Function Macros: */\r
+ #if defined(__DOXYGEN__)\r
+ /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end\r
+ * of the user application's main() function, as it can never return to the calling function.\r
+ */\r
+ void Scheduler_Start(void);\r
+ \r
+ /** Initializes the scheduler so that the scheduler functions can be called before the scheduler itself\r
+ * is started. This must be executed before any scheduler function calls other than Scheduler_Start(),\r
+ * and can be omitted if no such functions could be called before the scheduler is started.\r
+ */\r
+ void Scheduler_Init(void);\r
+ #else\r
+ #define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS);\r
+ \r
+ #define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS);\r
+ #endif\r
+\r
+ /* Type Defines: */\r
+ /** Type define for a pointer to a scheduler task. */\r
+ typedef void (*TaskPtr_t)(void);\r
+ \r
+ /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay\r
+ * possible.\r
+ */\r
+ typedef uint16_t SchedulerDelayCounter_t;\r
+ \r
+ /** Structure for holding a single task's information in the scheduler task list. */\r
+ typedef struct\r
+ {\r
+ TaskPtr_t Task; /**< Pointer to the task to execute. */\r
+ bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */\r
+ uint8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */\r
+ } TaskEntry_t; \r
+\r
+ /* Global Variables: */\r
+ /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type\r
+ * TaskEntry_t and can be manipulated as desired, although it is preferential that the proper Scheduler\r
+ * functions should be used instead of direct manipulation.\r
+ */\r
+ extern TaskEntry_t Scheduler_TaskList[];\r
+ \r
+ /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to\r
+ * TASK_RUN or TASK_STOP.\r
+ *\r
+ * \note This value should be treated as read-only, and never altered in user-code.\r
+ */\r
+ extern volatile uint8_t Scheduler_TotalTasks;\r
+\r
+ /** Contains the current scheduler tick count, for use with the delay functions. If the delay functions\r
+ * are used in the user code, this should be incremented each tick period so that the delays can be\r
+ * calculated.\r
+ */\r
+ extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;\r
+\r
+ /* Inline Functions: */\r
+ /** Resets the delay counter value to the current tick count. This should be called to reset the period\r
+ * for a delay in a task which is dependant on the current tick value.\r
+ *\r
+ * \param DelayCounter Counter which is storing the starting tick count for a given delay.\r
+ */\r
+ static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)\r
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;\r
+ static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)\r
+ {\r
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
+ {\r
+ *DelayCounter = Scheduler_TickCounter;\r
+ }\r
+ }\r
+ \r
+ /* Function Prototypes: */\r
+ /** Determines if the given tick delay has elapsed, based on the given .\r
+ *\r
+ * \param Delay The delay to test for, measured in ticks\r
+ * \param DelayCounter The counter which is storing the starting tick value for the delay\r
+ *\r
+ * \return Boolean true if the delay has elapsed, false otherwise\r
+ *\r
+ * Usage Example:\r
+ * \code\r
+ * static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up\r
+ * \r
+ * // Task runs every 10000 ticks, 10 seconds for this demo\r
+ * if (Scheduler_HasDelayElapsed(10000, &DelayCounter))\r
+ * {\r
+ * // Code to execute after delay interval elapsed here\r
+ * }\r
+ * \endcode\r
+ */\r
+ bool Scheduler_HasDelayElapsed(const uint16_t Delay,\r
+ SchedulerDelayCounter_t* const DelayCounter)\r
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);\r
+ \r
+ /** Sets the task mode for a given task.\r
+ *\r
+ * \param Task Name of the task whose status is to be changed\r
+ * \param TaskStatus New task status for the task (TASK_RUN or TASK_STOP)\r
+ */\r
+ void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus);\r
+ \r
+ /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their\r
+ * statuses changed at once.\r
+ *\r
+ * \param GroupID Value of the task group ID whose status is to be changed\r
+ * \param TaskStatus New task status for tasks in the specified group (TASK_RUN or TASK_STOP)\r
+ */\r
+ void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus);\r
+\r
+ /* Private Interface - For use in library only: */ \r
+ #if !defined(__DOXYGEN__)\r
+ /* Macros: */\r
+ #define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))\r
+ #define MAX_DELAYCTR_COUNT 0xFFFF\r
+\r
+ /* Inline Functions: */\r
+ static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) ATTR_ALWAYS_INLINE;\r
+ static inline void Scheduler_InitScheduler(const uint8_t TotalTasks)\r
+ {\r
+ Scheduler_TotalTasks = TotalTasks;\r
+ }\r
+ \r
+ static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE;\r
+ static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)\r
+ {\r
+ Scheduler_InitScheduler(TotalTasks);\r
+\r
+ for (;;)\r
+ {\r
+ TaskEntry_t* CurrTask = &Scheduler_TaskList[0];\r
+ \r
+ while (CurrTask != &Scheduler_TaskList[TotalTasks])\r
+ {\r
+ if (CurrTask->TaskStatus == TASK_RUN)\r
+ CurrTask->Task();\r
+\r
+ CurrTask++;\r
+ }\r
+ }\r
+ }\r
+ #endif\r
+ \r
+ /* Disable C linkage for C++ Compilers: */\r
+ #if defined(__cplusplus)\r
+ }\r
+ #endif\r
+ \r
+#endif\r
+\r
+/** @} */\r