Kaynağa Gözat

Version 1.8.3 number of addtions and improvements

 * support for task activation on a status request with arbitrary interval and number of iterations (0 and 1 are still default values)
 * implement waitForDelayed() method to allow task activation on the status request completion delayed for one current interval
 * added callback methods prototypes to all examples for Arduino IDE 1.6.6 compatibility
 * added several constants to be used as task parameters for readability (e.g, TASK_FOREVER, TASK_SECOND, etc.)
 * significant optimization of the scheduler's execute loop, including millis() rollover fix option
Anatoli Arkhipenko 10 yıl önce
ebeveyn
işleme
dc152db48e

+ 9 - 3
README

@@ -1,7 +1,6 @@
 Task Scheduler – cooperative multitasking for Arduino microcontrollers
 Task Scheduler – cooperative multitasking for Arduino microcontrollers
-Version 1.8.2: 2015-10-29
- 
- 
+Version 1.8.3: 2015-11-05
+  
 OVERVIEW:
 OVERVIEW:
 A lightweight implementation of cooperative multitasking (task scheduling) supporting:
 A lightweight implementation of cooperative multitasking (task scheduling) supporting:
 1. Periodic task execution (with dynamic execution period in milliseconds)
 1. Periodic task execution (with dynamic execution period in milliseconds)
@@ -62,3 +61,10 @@ v1.8.2:
     2015-10-27 - protection against infinite loop in OnEnable (if enable() methods are called within OnEnable)
     2015-10-27 - protection against infinite loop in OnEnable (if enable() methods are called within OnEnable)
     2015-10-29 - new currentLts() method in the scheduler class returns current task's LTS pointer in one call
     2015-10-29 - new currentLts() method in the scheduler class returns current task's LTS pointer in one call
 	
 	
+v1.8.3:
+    2015-11-05 - support for task activation on a status request with arbitrary interval and number of iterations (0 and 1 are still default values)
+    2015-11-05 - implement waitForDelayed() method to allow task activation on the status request completion delayed for one current interval
+    2015-11-09 - added callback methods prototypes to all examples for Arduino IDE 1.6.6 compatibility
+    2015-11-14 - added several constants to be used as task parameters for readability (e.g, TASK_FOREVER, TASK_SECOND, etc.)
+    2015-11-14 - significant optimization of the scheduler's execute loop, including millis() rollover fix option
+

+ 17 - 12
examples/Scheduler_example/Scheduler_example.ino

@@ -13,10 +13,16 @@
  
  
 #include <TaskScheduler.h>
 #include <TaskScheduler.h>
 
 
+// Callback methods prototypes
+void t1Callback();
+void t2Callback();
+void t3Callback();
+
+//Tasks
 Task t4();
 Task t4();
 Task t1(2000, 10, &t1Callback);
 Task t1(2000, 10, &t1Callback);
-Task t2(3000, -1, &t2Callback);
-Task t3(5000, -1, &t3Callback);
+Task t2(3000, TASK_FOREVER, &t2Callback);
+Task t3(5000, TASK_FOREVER, &t3Callback);
 
 
 Scheduler runner;
 Scheduler runner;
 
 
@@ -26,8 +32,8 @@ void t1Callback() {
     Serial.println(millis());
     Serial.println(millis());
     
     
     if (t1.isFirstIteration()) {
     if (t1.isFirstIteration()) {
-       t3.enable();
-       runner.addTask(t3);
+      runner.addTask(t3);
+      t3.enable();
       Serial.println("t1: enabled t3 and added to the chain");
       Serial.println("t1: enabled t3 and added to the chain");
     }
     }
     
     
@@ -55,12 +61,6 @@ void setup () {
   Serial.begin(115200);
   Serial.begin(115200);
   Serial.println("Scheduler TEST");
   Serial.println("Scheduler TEST");
   
   
-  
-  t1.enable();
-  Serial.println("Enabled t1");
-  t2.enable();
-  Serial.println("Enabled t2");
-  
   runner.init();
   runner.init();
   Serial.println("Initialized scheduler");
   Serial.println("Initialized scheduler");
   
   
@@ -69,11 +69,16 @@ void setup () {
   
   
   runner.addTask(t2);
   runner.addTask(t2);
   Serial.println("added t2");
   Serial.println("added t2");
-  
+
   delay(5000);
   delay(5000);
+  
+  t1.enable();
+  Serial.println("Enabled t1");
+  t2.enable();
+  Serial.println("Enabled t2");
 }
 }
 
 
 
 
 void loop () {
 void loop () {
   runner.execute();
   runner.execute();
-}
+}

+ 14 - 7
examples/Scheduler_example2/Scheduler_example2.ino

@@ -2,11 +2,16 @@
 #include <TaskScheduler.h>
 #include <TaskScheduler.h>
 
 
 Scheduler runner;
 Scheduler runner;
+// Callback methods prototypes
+void t1Callback();
+void t2Callback();
+void t3Callback(); 
 
 
+// Tasks
 Task t4();
 Task t4();
 Task t1(2000, 10, &t1Callback, &runner, true);  //adding task to the chain on creation
 Task t1(2000, 10, &t1Callback, &runner, true);  //adding task to the chain on creation
-Task t2(3000, -1, &t2Callback, &runner, true);  //adding task to the chain on creation
-Task t3(5000, -1, &t3Callback);
+Task t2(3000, TASK_FOREVER, &t2Callback, &runner, true);  //adding task to the chain on creation
+Task t3(5000, TASK_FOREVER, &t3Callback);
 
 
 // Test
 // Test
 // Initially only tasks 1 and 2 are enabled
 // Initially only tasks 1 and 2 are enabled
@@ -18,6 +23,8 @@ Task t3(5000, -1, &t3Callback);
 // Task1 disables Task3 on its last iteration and changed Task2 to run every 1/2 seconds
 // Task1 disables Task3 on its last iteration and changed Task2 to run every 1/2 seconds
 // Because Task2 interval is shorter than Scheduler default tick, loop() executes ecery 1/2 seconds now
 // Because Task2 interval is shorter than Scheduler default tick, loop() executes ecery 1/2 seconds now
 // At the end Task2 is the only task running every 1/2 seconds
 // At the end Task2 is the only task running every 1/2 seconds
+//
+// NOTE that t1 and t2 are affected by the delay() function in the setup() method and are scheduled immediately twice to "catch up" with millis().
 
 
 
 
 
 
@@ -28,8 +35,8 @@ void t1Callback() {
     Serial.println(millis());
     Serial.println(millis());
     
     
     if (t1.isFirstIteration()) {
     if (t1.isFirstIteration()) {
-       t3.enable();
-       runner.addTask(t3);
+      runner.addTask(t3);
+      t3.enable();
       Serial.println("t1: enabled t3 and added to the chain");
       Serial.println("t1: enabled t3 and added to the chain");
     }
     }
     
     
@@ -65,6 +72,6 @@ void loop () {
   
   
   runner.execute();
   runner.execute();
   
   
-  Serial.println("Loop ticks at: ");
-  Serial.println(millis());
-}
+//  Serial.println("Loop ticks at: ");
+//  Serial.println(millis());
+}

+ 13 - 4
examples/Scheduler_example3/Scheduler_example3.ino

@@ -1,7 +1,7 @@
 /**
 /**
  * TaskScheduler Test of OnEnable and OnDisable methods and illustration of using wrapper tasks for timout purposes
  * TaskScheduler Test of OnEnable and OnDisable methods and illustration of using wrapper tasks for timout purposes
  *
  *
- * 	A wrapper task runs every 30 seconds and initiates the test case
+ * 	A wrapper task runs every 10 seconds and initiates the test case
  * 	Another task is run once for 5 seconds, and serves as a LED blinking timeout - 5 seconds
  * 	Another task is run once for 5 seconds, and serves as a LED blinking timeout - 5 seconds
  * 	Finally, a dedicated task which controls LED is running periodically until stopped, and makes the LED blink with 0.5 to 1 second interval. 
  * 	Finally, a dedicated task which controls LED is running periodically until stopped, and makes the LED blink with 0.5 to 1 second interval. 
  *
  *
@@ -14,9 +14,17 @@
 
 
 Scheduler ts;
 Scheduler ts;
 
 
-Task tWrapper(30000L, -1, &WrapperCallback, &ts, true);
-Task tBlink(5000, 1, NULL, &ts, false, &BlinkOnEnable, &BlinkOnDisable);
-Task tLED(0, -1, NULL, &ts, false, NULL, &LEDOff);
+// Callback methods prototypes
+void WrapperCallback();
+bool BlinkOnEnable();
+void BlinkOnDisable();
+void LEDOn();
+void LEDOff();
+
+// Tasks
+Task tWrapper(10000L, TASK_FOREVER, &WrapperCallback, &ts, true);
+Task tBlink(5000, TASK_ONCE, NULL, &ts, false, &BlinkOnEnable, &BlinkOnDisable);
+Task tLED(0, TASK_FOREVER, NULL, &ts, false, NULL, &LEDOff);
 
 
 void WrapperCallback() {
 void WrapperCallback() {
 	tBlink.restartDelayed(); // LED blinking is initiated
 	tBlink.restartDelayed(); // LED blinking is initiated
@@ -61,6 +69,7 @@ void LEDOff () {
 
 
 void setup() {
 void setup() {
 // put your setup code here, to run once:
 // put your setup code here, to run once:
+  pinMode(LEDPIN, OUTPUT);
 }
 }
 
 
 void loop() {
 void loop() {

+ 10 - 2
examples/Scheduler_example4_StatusRequest/Scheduler_example4_StatusRequest.ino

@@ -13,7 +13,15 @@ StatusRequest st;
 
 
 Scheduler ts; 
 Scheduler ts; 
 
 
-Task t1(5000, 1, &Callback1, &ts, true, NULL, &Disable1);
+// Callback methods prototypes
+void Callback1();
+void Disable1();
+void Callback2();
+void Callback3();
+void PrepareStatus();
+
+// Tasks
+Task t1(5000, TASK_ONCE, &Callback1, &ts, true, NULL, &Disable1);
 Task t2(&Callback2, &ts);
 Task t2(&Callback2, &ts);
 Task t3(&Callback3, &ts);
 Task t3(&Callback3, &ts);
 
 
@@ -77,4 +85,4 @@ void loop() {
 
 
   ts.execute();
   ts.execute();
 
 
-}
+}

+ 17 - 10
examples/Scheduler_example5_StatusRequest/Scheduler_example5_StatusRequest.ino

@@ -7,22 +7,29 @@
 
 
 #define _TASK_SLEEP_ON_IDLE_RUN
 #define _TASK_SLEEP_ON_IDLE_RUN
 #define _TASK_STATUS_REQUEST
 #define _TASK_STATUS_REQUEST
-
 #include <TaskScheduler.h>
 #include <TaskScheduler.h>
 
 
-
-
-
 StatusRequest measure;
 StatusRequest measure;
 
 
 Scheduler ts; 
 Scheduler ts; 
 
 
-Task tCycle(10000, -1, &CycleCallback, &ts, true);
-Task tMeasure(1000, 1, &MeasureCallback, &ts, false, &MeasureEnable, &MeasureDisable);
+// Callback methods prototypes
+void CycleCallback();
+void MeasureCallback(); 
+bool MeasureEnable();
+void MeasureDisable();
+void CalcCallback();
+void S1Callback(); bool S1Enable();
+void S2Callback(); bool S2Enable();
+void S3Callback(); bool S3Enable();
+
+// Tasks
+Task tCycle(10000, TASK_FOREVER, &CycleCallback, &ts, true);
+Task tMeasure(1000, TASK_ONCE, &MeasureCallback, &ts, false, &MeasureEnable, &MeasureDisable);
 Task tCalculate(&CalcCallback, &ts);
 Task tCalculate(&CalcCallback, &ts);
-Task tSensor1(0, 1, &S1Callback, &ts, false, &S1Enable);
-Task tSensor2(0, 1, &S2Callback, &ts, false, &S2Enable);
-Task tSensor3(0, 1, &S3Callback, &ts, false, &S3Enable);
+Task tSensor1(0, TASK_ONCE, &S1Callback, &ts, false, &S1Enable);
+Task tSensor2(0, TASK_ONCE, &S2Callback, &ts, false, &S2Enable);
+Task tSensor3(0, TASK_ONCE, &S3Callback, &ts, false, &S3Enable);
 
 
 
 
 long distance, d1, d2, d3;
 long distance, d1, d2, d3;
@@ -162,4 +169,4 @@ void loop() {
   
   
   ts.execute();
   ts.execute();
 
 
-}
+}

+ 8 - 3
examples/Scheduler_example6_IDLE/Scheduler_example6_IDLE.ino

@@ -38,8 +38,13 @@ C1 is scenario 2) is much higher than in scenario 1) because processor is put to
 
 
 Scheduler ts;
 Scheduler ts;
 
 
-Task c(10, -1, &Count, &ts);
-Task t(10000, 1, NULL, &ts, true, &tOn, &tOff);
+// Callback methods prototypes
+void Count();
+bool tOn(); void tOff();
+
+// Tasks
+Task c(10, TASK_FOREVER, &Count, &ts);
+Task t(10000, TASK_ONCE, NULL, &ts, true, &tOn, &tOff);
 
 
 
 
 volatile unsigned long c1, c2;
 volatile unsigned long c1, c2;
@@ -74,4 +79,4 @@ void loop() {
   // put your main code here, to run repeatedly:
   // put your main code here, to run repeatedly:
   ts.execute();
   ts.execute();
   c1++;
   c1++;
-}
+}

+ 9 - 5
examples/Scheduler_example7_WDT/Scheduler_example7_WDT.ino

@@ -18,14 +18,18 @@
 
 
 Scheduler ts;
 Scheduler ts;
 
 
+// Callback methods prototypes
+void TaskCB(); 
+void HB(); bool HBOn(); void HBOff();
+
 // Three tasks emulating accidental infinite loop
 // Three tasks emulating accidental infinite loop
-Task tTask1(1000, -1, &TaskCB, &ts, true);
-Task tTask2(1000, -1, &TaskCB, &ts, true);
-Task tTask3(1000, -1, &TaskCB, &ts, true);
+Task tTask1(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
+Task tTask2(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
+Task tTask3(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
 
 
 // Heartbeat task - resetting the watchdog timer periodically
 // Heartbeat task - resetting the watchdog timer periodically
 // Initiates WDT on enable, and deactivates it on disable
 // Initiates WDT on enable, and deactivates it on disable
-Task tHB(500, -1, &HB, &ts, false, &HBOn, &HBOff);
+Task tHB(500, TASK_FOREVER, &HB, &ts, false, &HBOn, &HBOff);
 
 
 /**
 /**
  * Emulating task callback function
  * Emulating task callback function
@@ -125,4 +129,4 @@ void setup() {
  */
  */
 void loop() {
 void loop() {
   ts.execute();
   ts.execute();
-}
+}

+ 10 - 5
examples/Scheduler_example8_LTS/Scheduler_example8_LTS.ino

@@ -23,16 +23,21 @@
 
 
 Scheduler ts;
 Scheduler ts;
 
 
+// Callback methods prototypes
+void Calculate(); bool CalcOn();
+bool WrapperOn(); void WrapperOff(); 
+
+// Tasks
 // Calculator tasks.
 // Calculator tasks.
 // Note that all three tasks use the same callback methods
 // Note that all three tasks use the same callback methods
 // They will be updating specific variables based on the
 // They will be updating specific variables based on the
 // Locat Task Storage pointers 
 // Locat Task Storage pointers 
-Task t1(1000, -1, &Calculate, &ts, false, &CalcOn); 
-Task t2(1000, -1, &Calculate, &ts, false, &CalcOn); 
-Task t3(1000, -1, &Calculate, &ts, false, &CalcOn);
+Task t1(TASK_SECOND, TASK_FOREVER, &Calculate, &ts, false, &CalcOn); 
+Task t2(TASK_SECOND, TASK_FOREVER, &Calculate, &ts, false, &CalcOn); 
+Task t3(TASK_SECOND, TASK_FOREVER, &Calculate, &ts, false, &CalcOn);
 // add more calc tasks here if necessary
 // add more calc tasks here if necessary
 
 
-Task tWrapper(5000, 1, NULL, &ts, false, &WrapperOn, &WrapperOff); 
+Task tWrapper(5*TASK_SECOND, TASK_ONCE, NULL, &ts, false, &WrapperOn, &WrapperOff); 
 
 
 // The below structure is an object referenced by LTS pointer
 // The below structure is an object referenced by LTS pointer
 typedef struct {
 typedef struct {
@@ -139,4 +144,4 @@ void setup() {
 
 
 void loop() {
 void loop() {
   ts.execute();
   ts.execute();
-}
+}

BIN
extras/TaskScheduler.doc


+ 143 - 51
extras/TaskScheduler.html

@@ -6,7 +6,7 @@
 	<META NAME="GENERATOR" CONTENT="LibreOffice 3.5  (Linux)">
 	<META NAME="GENERATOR" CONTENT="LibreOffice 3.5  (Linux)">
 	<META NAME="CREATED" CONTENT="20150206;16300000">
 	<META NAME="CREATED" CONTENT="20150206;16300000">
 	<META NAME="CHANGEDBY" CONTENT="Anatoli Arkhipenko">
 	<META NAME="CHANGEDBY" CONTENT="Anatoli Arkhipenko">
-	<META NAME="CHANGED" CONTENT="20151029;23230000">
+	<META NAME="CHANGED" CONTENT="20151105;22050000">
 	<META NAME="Info 1" CONTENT="">
 	<META NAME="Info 1" CONTENT="">
 	<META NAME="Info 2" CONTENT="">
 	<META NAME="Info 2" CONTENT="">
 	<META NAME="Info 3" CONTENT="">
 	<META NAME="Info 3" CONTENT="">
@@ -15,8 +15,8 @@
 	<!--
 	<!--
 		@page { margin: 0.79in }
 		@page { margin: 0.79in }
 		P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 0; orphans: 0 }
 		P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 0; orphans: 0 }
-		P.western { font-family: "Liberation Serif", "MS PMincho", serif; font-size: 12pt; so-language: en-US }
-		P.cjk { font-family: "WenQuanYi Micro Hei", "MS Mincho"; font-size: 12pt }
+		P.western { font-family: "Liberation Serif", "Times New Roman", serif; font-size: 12pt; so-language: en-US }
+		P.cjk { font-family: "WenQuanYi Micro Hei", "MS Mincho"; font-size: 12pt; so-language: zh-CN }
 		P.ctl { font-family: "Lohit Hindi", "MS Mincho"; font-size: 12pt; so-language: hi-IN }
 		P.ctl { font-family: "Lohit Hindi", "MS Mincho"; font-size: 12pt; so-language: hi-IN }
 		A:link { color: #0000ff }
 		A:link { color: #0000ff }
 	-->
 	-->
@@ -28,7 +28,7 @@ Scheduler</B></FONT></P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>cooperative
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>cooperative
 multitasking for Arduino microcontrollers</B></P>
 multitasking for Arduino microcontrollers</B></P>
 <P CLASS="western" STYLE="margin-bottom: 0in; border-top: none; border-bottom: 1px solid #000000; border-left: none; border-right: none; padding-top: 0in; padding-bottom: 0.01in; padding-left: 0in; padding-right: 0in">
 <P CLASS="western" STYLE="margin-bottom: 0in; border-top: none; border-bottom: 1px solid #000000; border-left: none; border-right: none; padding-top: 0in; padding-bottom: 0.01in; padding-left: 0in; padding-right: 0in">
-<FONT SIZE=2 STYLE="font-size: 11pt"><B>Version 1.8.2: 2015-10-27</B></FONT></P>
+<FONT SIZE=2 STYLE="font-size: 11pt"><B>Version 1.8.3: 2015-11-05</B></FONT></P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>OVERVIEW</B>:</P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>OVERVIEW</B>:</P>
@@ -122,7 +122,7 @@ than the Scheduler's <B>execute</B>() method).</P>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <B>Below is the flowchart of a Task lifecycle:</B></P>
 <B>Below is the flowchart of a Task lifecycle:</B></P>
-<P CLASS="western" STYLE="margin-bottom: 0in"><IMG SRC="TaskScheduler_html.png" NAME="graphics1" ALIGN=BOTTOM WIDTH=664 HEIGHT=690 BORDER=0></P>
+<P CLASS="western" STYLE="margin-bottom: 0in"><IMG SRC="TaskScheduler_html_m68472eb8.png" NAME="graphics1" ALIGN=BOTTOM WIDTH=664 HEIGHT=655 BORDER=0></P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>TaskScheduler</B>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>TaskScheduler</B>
@@ -276,6 +276,19 @@ LTS pointer to the appropriate pointer type.
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>
+<P CLASS="western" STYLE="margin-bottom: 0in">#define
+<B>_TASK_ROLLOVER_FIX</B></P>
+<P CLASS="western" STYLE="margin-bottom: 0in">…will compile
+TaskScheduler with support for millis() rollover approximately every
+47 days. Only required if you plan for your sketch to run for
+extended amount of time (over 47 days).</P>
+<P CLASS="western" STYLE="margin-bottom: 0in">The problem here is
+when scheduler calculates next execution time for a task, a rollover
+may place next execution time “in the past” and cause task to be
+invoked incorrectly once every 47 days. 
+</P>
+<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
+</P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>NOTE: </B>above
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>NOTE: </B>above
 parameters are<B> DISABLED </B>by default, and need to be explicitly
 parameters are<B> DISABLED </B>by default, and need to be explicitly
 enabled by placing appropriate #define statements in front of the
 enabled by placing appropriate #define statements in front of the
@@ -488,7 +501,13 @@ is a task which was enabled and requires execution.
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
-<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>NOTE:
+</B><SPAN STYLE="font-weight: normal">if task</SPAN> being enabled is
+not assigned to a scheduler and is not part of execution chain, then
+task <B>will not</B> be enabled.</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>NOTE:
 </B>enable() invokes task’s <B>OnEnable</B> method (if not NULL)
 </B>enable() invokes task’s <B>OnEnable</B> method (if not NULL)
 <B>immediately</B>, which can prepare task for execution. <B>OnEnable</B>
 <B>immediately</B>, which can prepare task for execution. <B>OnEnable</B>
 must return a value of <B>true</B> for task to be enabled. If
 must return a value of <B>true</B> for task to be enabled. If
@@ -662,17 +681,38 @@ METHODS:</B></P>
 <BR>
 <BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
-<B>void waitFor(StatusRequest* aStatusRequest);</B></P>
+<B>void waitFor(StatusRequest* aStatusRequest, unsigned long
+aInterval = 0, long aIterations = 1)</B></P>
+<P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
+<B>void waitForDelayed(StatusRequest* aStatusRequest, unsigned long
+aInterval = 0, long aIterations = 1)</B></P>
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <BR>
 <BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
-compiled with support for Status Requests, this method makes task
+compiled with support for Status Requests, these methods make task
 wait for the completion of <B>aStatusRequest</B> event. 
 wait for the completion of <B>aStatusRequest</B> event. 
 </P>
 </P>
-<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>waitFor()
-</B>sets tasks interval to <B>0 (zero)</B> for immediate execution
-when event happens, and also sets the number of <B>iterations to 1</B>.</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">By
+default <B>waitFor() </B>sets tasks interval to <B>0 (zero)</B> for
+immediate execution when event happens, and also sets the number of
+<B>iterations to 1</B>. However, you can specify different interval
+and number of iterations. 
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">By
+default <B>waitForDelayed() </B>sets tasks interval to a supplied
+value or (if omitted or zero) keeps the current interval, so delayed
+execution will take place when the event happens.  It also sets the
+number of <B>iterations to 1</B><SPAN STYLE="font-weight: normal"> by
+default if not supplied</SPAN>.  
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">When
+Status Request object completes, all tasks waiting on it are executed
+during next scheduling pass. Tasks waiting via <B>waitFor</B>()
+method are executed immediately. Tasks waiting via <B>waitForDelayed</B>()
+method are activated, but executed after current or supplied interval
+delay. 
+</P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
 aStatusRequest</B> should be “activated” by calling <B>setWaiting()
 aStatusRequest</B> should be “activated” by calling <B>setWaiting()
 </B>method before making a task wait on it. Otherwise, the task will
 </B>method before making a task wait on it. Otherwise, the task will
@@ -703,8 +743,8 @@ a StatusReqeust object this Task was waiting on.
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
-<P CLASS="western" STYLE="margin-bottom: 0in"><B>TASK ID, CONTROL
-POINTS METHODS:</B></P>
+<P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
+<B>TASK ID, CONTROL POINTS METHODS:</B></P>
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <BR>
 <BR>
 </P>
 </P>
@@ -929,6 +969,13 @@ statements after <B>execute</B> inside the <B>loop()</B>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
+<P CLASS="western" STYLE="margin-bottom: 0in"><B>bool isOverrun()</B></P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
+library is compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
+enabled, this method returns <B>true</B><SPAN STYLE="font-weight: normal">
+if currently invoked task has overrun its scheduled start time when
+it was invoked. Returns </SPAN><B>false</B><SPAN STYLE="font-weight: normal">
+if task has been invoked according to schedule.</SPAN></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
@@ -955,7 +1002,7 @@ status of “completed” on creation.
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>void
 <P CLASS="western" STYLE="margin-bottom: 0in"><B>void
-setWaiting(unsigned int aCount)</B></P>
+setWaiting(unsigned int aCount = 1)</B></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Activates
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Activates
 Status Request object. By default each object is set to wait on one
 Status Request object. By default each object is set to wait on one
 event only, however, if <B>aCount</B> is supplied, Status Request can
 event only, however, if <B>aCount</B> is supplied, Status Request can
@@ -1023,6 +1070,46 @@ completion of a request.</P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
 <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
+<B>CONSTANTS:</B></P>
+<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; page-break-after: avoid">
+<B>TASK_SECOND	(1000)</B></P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">Task
+interval of 1 second</P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; page-break-after: avoid">
+<B>TASK_MINUTE	(60000)</B></P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">Task
+interval of 1 minute</P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; page-break-after: avoid">
+<B>TASK_HOUR		(3600000)</B></P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">Task
+interval of 1 hour</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; page-break-after: avoid">
+<B>TASK_FOREVER	(-1)</B></P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">Task
+number of iterations for infinite number of iterations</P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; page-break-after: avoid">
+<B>TASK_ONCE		(1)</B></P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">Task
+single iteration</P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in; page-break-after: avoid">
+<B>TASK_IMMEDIATE	(0)</B></P>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">Task
+interval for immediate execution</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
+</P>
+<P CLASS="western" STYLE="margin-bottom: 0in; page-break-before: always; page-break-after: avoid">
 <B>IMPLEMENTATION SCENARIOS AND IDEAS:</B></P>
 <B>IMPLEMENTATION SCENARIOS AND IDEAS:</B></P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>
@@ -1048,11 +1135,11 @@ becomes a task:</P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-<B>tMeasure</B> (TMEASURE_INTERVAL*SECOND, -1,
+<B>tMeasure</B> (TMEASURE_INTERVAL*SECOND, TASK_FOREVER,
 &amp;measureCallback);<BR>Task <B>tWater</B>  
 &amp;measureCallback);<BR>Task <B>tWater</B>  
 (TWATER_INTERVAL*SECOND, RETRIES, &amp;waterCallback);<BR>Task
 (TWATER_INTERVAL*SECOND, RETRIES, &amp;waterCallback);<BR>Task
-<B>tDisplay</B> (TDISPLAY_INTERVAL*SECOND, -1, &amp;displayCallback);
-<BR></FONT></FONT><BR>
+<B>tDisplay</B> (TDISPLAY_INTERVAL*SECOND, TASK_FOREVER,
+&amp;displayCallback); <BR></FONT></FONT><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
 </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>taskManager</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>;</FONT></FONT><BR><BR>
 </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>taskManager</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>;</FONT></FONT><BR><BR>
@@ -1065,7 +1152,7 @@ to run once for every time the pump is turned on:</P>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>tWaterOff</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>
 </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>tWaterOff</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>
-(WATERTIME*SECOND, 1,</FONT></FONT><FONT FACE="Courier New, monospace">
+(WATERTIME*SECOND, TASK_ONCE,</FONT></FONT><FONT FACE="Courier New, monospace">
 &amp;waterOffCallback);</FONT><BR><BR>
 &amp;waterOffCallback);</FONT><BR><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-bottom: 0in">Example of the callback
 <P CLASS="western" STYLE="margin-bottom: 0in">Example of the callback
@@ -1084,9 +1171,9 @@ tWater.enableDelayed();<BR>}</FONT></FONT></P>
 waterCallback() {<BR>    if (tWater.getIterations()) {</FONT></FONT></P>
 waterCallback() {<BR>    if (tWater.getIterations()) {</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
 If this is not the last iteration = turn the pump on<BR>     
 If this is not the last iteration = turn the pump on<BR>     
-motorOn();<BR>      tWaterOff.set(parameters.watertime * SECOND, 1,
-&amp;waterOffCallback);<BR>      tWaterOff.enableDelayed();<BR>     
-return;<BR>    }</FONT></FONT></P>
+motorOn();<BR>      tWaterOff.set(parameters.watertime * TASK_SECOND,
+TASK_ONCE, &amp;waterOffCallback);<BR>     
+tWaterOff.enableDelayed();<BR>      return;<BR>    }</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
 We could not reach target humidity – something is wrong<BR>   
 We could not reach target humidity – something is wrong<BR>   
 motorOff;<BR>    taskManager.disableAll();<BR>    tError.enable();<BR>}</FONT></FONT></P>
 motorOff;<BR>    taskManager.disableAll();<BR>    tError.enable();<BR>}</FONT></FONT></P>
@@ -1146,7 +1233,7 @@ Blinking LED 2 times a second could be achieved this way</FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
 ts;</FONT></FONT></P>
 ts;</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tLedBlinker (500, -1, &amp;ledOnCallback, &amp;ts, true);</FONT></FONT></P>
+tLedBlinker (500, TASK_FOREVER, &amp;ledOnCallback, &amp;ts, true);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
@@ -1212,7 +1299,7 @@ this case, define a tasks with two callbacks:</FONT></P>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-<B>tWork</B> (T_INTERVAL, -1, &amp;workCallbackInit);</FONT></FONT></P>
+<B>tWork</B> (T_INTERVAL, TASK_FOREVER, &amp;workCallbackInit);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">…</P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">…</P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
@@ -1290,16 +1377,17 @@ determine the length of ultrasonic pulse.</FONT></P>
 &lt;PinChangeInt.h&gt;<BR><BR><BR>#define  TRIGGERPIN 5<BR>#define 
 &lt;PinChangeInt.h&gt;<BR><BR><BR>#define  TRIGGERPIN 5<BR>#define 
 ECHOPIN    6<BR><BR>Output&lt;TRIGGERPIN&gt; 
 ECHOPIN    6<BR><BR>Output&lt;TRIGGERPIN&gt; 
 pTrigger;<BR>Input&lt;ECHOPIN&gt;      pEcho;<BR><BR>Scheduler
 pTrigger;<BR>Input&lt;ECHOPIN&gt;      pEcho;<BR><BR>Scheduler
-r;<BR><BR>Task  tMeasure(1000, -1, &amp;measureCallback, &amp;r,
-true);<BR>Task  tDisplay(1000, -1, &amp;displayCallback, &amp;r,
-true);<BR>Task  tPing(0, 1, &amp;pingCalcCallback, &amp;r,
-false);<BR><BR><BR>volatile bool pulseBusy = false;<BR>volatile bool
-pulseTimeout = false;<BR>volatile unsigned long pulseStart =
-0;<BR>volatile unsigned long pulseStop = 0;<BR>volatile unsigned long
-pingDistance = 0;<BR><BR><BR>void pingTrigger(unsigned long aTimeout)
-{<BR>  if (pulseBusy) return;  // do not trigger if in the middle of
-a pulse<BR>  if (pEcho == HIGH) return; // do not trigger if ECHO pin
-is high<BR>  <BR>  pulseBusy = true;<BR>  pulseTimeout = false;</FONT></FONT></P>
+r;<BR><BR>Task  tMeasure(TASK_SECOND, TASK_FOREVER, &amp;measureCallback,
+&amp;r, true);<BR>Task  tDisplay(TASK_SECOND, TASK_FOREVER,
+&amp;displayCallback, &amp;r, true);<BR>Task  tPing(TASK_IMMEDIATE,
+TASK_ONCE, &amp;pingCalcCallback, &amp;r, false);<BR><BR><BR>volatile
+bool pulseBusy = false;<BR>volatile bool pulseTimeout =
+false;<BR>volatile unsigned long pulseStart = 0;<BR>volatile unsigned
+long pulseStop = 0;<BR>volatile unsigned long pingDistance =
+0;<BR><BR><BR>void pingTrigger(unsigned long aTimeout) {<BR>  if
+(pulseBusy) return;  // do not trigger if in the middle of a pulse<BR>
+ if (pEcho == HIGH) return; // do not trigger if ECHO pin is high<BR>
+ <BR>  pulseBusy = true;<BR>  pulseTimeout = false;</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><BR>
  pTrigger = LOW;<BR>  delayMicroseconds(4);<BR>  pTrigger = HIGH;<BR><BR>
  pTrigger = LOW;<BR>  delayMicroseconds(4);<BR>  pTrigger = HIGH;<BR><BR>
  tPing.setInterval (aTimeout);<BR><BR>  delayMicroseconds(10);<BR> 
  tPing.setInterval (aTimeout);<BR><BR>  delayMicroseconds(10);<BR> 
@@ -1396,12 +1484,13 @@ ts;</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tWrapper(30000, -1, &amp;WrapperCallback, &amp;ts, true);</FONT></FONT></P>
+tWrapper(30000, TASK_FOREVER, &amp;WrapperCallback, &amp;ts, true);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tBlink(5000, 1, NULL, &amp;ts, false, &amp;BlinkOnEnable,
+tBlink(5000, TASK_ONCE, NULL, &amp;ts, false, &amp;BlinkOnEnable,
 &amp;BlinkOnDisable);</FONT></FONT></P>
 &amp;BlinkOnDisable);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tLED(0, -1, NULL, &amp;ts, false, NULL, &amp;LEDOff);</FONT></FONT></P>
+tLED(TASK_IMMEDIATE, TASK_FOREVER, NULL, &amp;ts, false, NULL,
+&amp;LEDOff);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
@@ -1582,18 +1671,21 @@ ts; </FONT></FONT>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tCycle(10000, -1, &amp;CycleCallback, &amp;ts, true);</FONT></FONT></P>
+tCycle(10000, TASK_FOREVER, &amp;CycleCallback, &amp;ts, true);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tMeasure(1000, 1, &amp;MeasureCallback, &amp;ts, false,
-&amp;MeasureEnable, &amp;MeasureDisable);</FONT></FONT></P>
+tMeasure(TASK_SECOND, TASK_ONCE, &amp;MeasureCallback, &amp;ts,
+false, &amp;MeasureEnable, &amp;MeasureDisable);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 tCalculate(&amp;CalcCallback, &amp;ts);</FONT></FONT></P>
 tCalculate(&amp;CalcCallback, &amp;ts);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tSensor1(0, 1, &amp;S1Callback, &amp;ts, false, &amp;S1Enable);</FONT></FONT></P>
+tSensor1(TASK_IMMEDIATE, TASK_ONCE, &amp;S1Callback, &amp;ts, false,
+&amp;S1Enable);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tSensor2(0, 1, &amp;S2Callback, &amp;ts, false, &amp;S2Enable);</FONT></FONT></P>
+tSensor2(TASK_IMMEDIATE, TASK_ONCE, &amp;S2Callback, &amp;ts, false,
+&amp;S2Enable);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
-tSensor3(0, 1, &amp;S3Callback, &amp;ts, false, &amp;S3Enable);</FONT></FONT></P>
+tSensor3(TASK_IMMEDIATE, TASK_ONCE, &amp;S3Callback, &amp;ts, false,
+&amp;S3Enable);</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
@@ -1973,13 +2065,13 @@ that both tasks refer to the same callback methods)</FONT></FONT></P>
 </P>
 </P>
 <P LANG="" CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">
 <P LANG="" CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">
 <FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler ts;</FONT></FONT></P>
 <FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler ts;</FONT></FONT></P>
-<P LANG="" CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">
-<FONT FACE="Courier New, monospace"><FONT SIZE=2>Task t1(100, -1,
-&amp;Measure, &amp;ts, false, &amp;MeasureOn); </FONT></FONT>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><SPAN LANG="">Task
+t1(100, </SPAN>TASK_FOREVER<SPAN LANG="">, &amp;Measure, &amp;ts,
+false, &amp;MeasureOn); </SPAN></FONT></FONT>
 </P>
 </P>
-<P LANG="" CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in">
-<FONT FACE="Courier New, monospace"><FONT SIZE=2>Task t2(100, -1,
-&amp;Measure, &amp;ts, false, &amp;MeasureOn); </FONT></FONT>
+<P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><SPAN LANG="">Task
+t2(100, </SPAN>TASK_FOREVER<SPAN LANG="">, &amp;Measure, &amp;ts,
+false, &amp;MeasureOn); </SPAN></FONT></FONT>
 </P>
 </P>
 <P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-left: 0.98in; margin-bottom: 0in"><BR>
 </P>
 </P>
@@ -2047,9 +2139,9 @@ information and implementation options.</FONT></FONT></P>
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Real
 <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Real
 time examples of TaskScheduler are available here:</FONT></FONT></P>
 time examples of TaskScheduler are available here:</FONT></FONT></P>
 <OL>
 <OL>
-	<LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT COLOR="#0000ff"><U><A HREF="http://www.instructables.com/id/APIS-Automated-Plant-Irrigation-System/"><FONT FACE="Courier New, monospace"><FONT SIZE=2>http://www.instructables.com/id/APIS-Automated-Plant-Irrigation-System/</FONT></FONT></A></U></FONT></P>
-	<LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT COLOR="#0000ff"><U><A HREF="http://www.instructables.com/id/Wave-your-hand-to-control-OWI-Robotic-Arm-no-strin/"><FONT FACE="Courier New, monospace"><FONT SIZE=2>http://www.instructables.com/id/Wave-your-hand-to-control-OWI-Robotic-Arm-no-strin/</FONT></FONT></A></U></FONT></P>
-	<LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT COLOR="#0000ff"><U><A HREF="http://www.instructables.com/id/Arduino-Nano-based-Hexbug-Scarab-Robotic-Spider"><FONT FACE="Courier New, monospace"><FONT SIZE=2>http://www.instructables.com/id/Arduino-Nano-based-Hexbug-Scarab-Robotic-Spider</FONT></FONT></A></U></FONT></P>
+	<LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT COLOR="#0000ff"><U><A HREF="http://www.instructables.com/id/APIS-Automated-Plant-Irrigation-System/"><FONT FACE="Courier New, monospace">http://www.instructables.com/id/APIS-Automated-Plant-Irrigation-System/</FONT></A></U></FONT></P>
+	<LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT COLOR="#0000ff"><U><A HREF="http://www.instructables.com/id/Wave-your-hand-to-control-OWI-Robotic-Arm-no-strin/"><FONT FACE="Courier New, monospace">http://www.instructables.com/id/Wave-your-hand-to-control-OWI-Robotic-Arm-no-strin/</FONT></A></U></FONT></P>
+	<LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT COLOR="#0000ff"><U><A HREF="http://www.instructables.com/id/Arduino-Nano-based-Hexbug-Scarab-Robotic-Spider"><FONT FACE="Courier New, monospace">http://www.instructables.com/id/Arduino-Nano-based-Hexbug-Scarab-Robotic-Spider</FONT></A></U></FONT></P>
 </OL>
 </OL>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
 </P>
 </P>

+ 14 - 0
keywords.txt

@@ -52,6 +52,7 @@ pending	KEYWORD2
 completed	KEYWORD2
 completed	KEYWORD2
 getStatus	KEYWORD2
 getStatus	KEYWORD2
 waitFor	KEYWORD2
 waitFor	KEYWORD2
+waitForDelayed	KEYWORD2
 getStatusRequest	KEYWORD2
 getStatusRequest	KEYWORD2
 setId	KEYWORD2
 setId	KEYWORD2
 getId	KEYWORD2
 getId	KEYWORD2
@@ -59,8 +60,21 @@ setControlPoint	KEYWORD2
 getControlPoint	KEYWORD2
 getControlPoint	KEYWORD2
 setLtsPointer	KEYWORD2
 setLtsPointer	KEYWORD2
 getLtsPointer	KEYWORD2
 getLtsPointer	KEYWORD2
+isOverrun	KEYWORD2
 
 
 #######################################
 #######################################
 # Constants (LITERAL1)
 # Constants (LITERAL1)
+TASK_SECOND	LITERAL1
+TASK_MINUTE	LITERAL1
+TASK_HOUR	LITERAL1
+TASK_FOREVER	LITERAL1
+TASK_IMMEDIATE	LITERAL1
+TASK_ONCE	LITERAL1
+_TASK_TIMECRITICAL	LITERAL1
+_TASK_SLEEP_ON_IDLE_RUN	LITERAL1
+_TASK_STATUS_REQUEST	LITERAL1
+_TASK_WDT_IDS	LITERAL1
+_TASK_LTS_POINTER	LITERAL1
+_TASK_ROLLOVER_FIX	LITERAL1
 #######################################
 #######################################
 
 

+ 1 - 1
library.properties

@@ -1,5 +1,5 @@
 name=TaskScheduler
 name=TaskScheduler
-version=1.8.2
+version=1.8.3
 author=Anatoli Arkhipenko <arkhipenko@hotmail.com>
 author=Anatoli Arkhipenko <arkhipenko@hotmail.com>
 maintainer=Anatoli Arkhipenko <arkhipenko@hotmail.com>
 maintainer=Anatoli Arkhipenko <arkhipenko@hotmail.com>
 sentence=A light-weight cooperative multitasking library for arduino microcontrollers.
 sentence=A light-weight cooperative multitasking library for arduino microcontrollers.

+ 129 - 84
src/TaskScheduler.h

@@ -50,6 +50,13 @@
 //    2015-10-27 - bug: currentTask() method returns incorrect Task reference if called within OnEnable and OnDisable methods
 //    2015-10-27 - bug: currentTask() method returns incorrect Task reference if called within OnEnable and OnDisable methods
 //    2015-10-27 - protection against infinite loop in OnEnable (if enable() methods are called within OnEnable)
 //    2015-10-27 - protection against infinite loop in OnEnable (if enable() methods are called within OnEnable)
 //    2015-10-29 - new currentLts() method in the scheduler class returns current task's LTS pointer in one call
 //    2015-10-29 - new currentLts() method in the scheduler class returns current task's LTS pointer in one call
+//
+// v1.8.3:
+//    2015-11-05 - support for task activation on a status request with arbitrary interval and number of iterations (0 and 1 are still default values)
+//    2015-11-05 - implement waitForDelayed() method to allow task activation on the status request completion delayed for one current interval
+//    2015-11-09 - added callback methods prototypes to all examples for Arduino IDE 1.6.6 compatibility
+//    2015-11-14 - added several constants to be used as task parameters for readability (e.g, TASK_FOREVER, TASK_SECOND, etc.)
+//    2015-11-14 - significant optimization of the scheduler's execute loop, including millis() rollover fix option
 
 
 
 
 /* ============================================
 /* ============================================
@@ -92,6 +99,7 @@ THE SOFTWARE.
  *	#define _TASK_STATUS_REQUEST    // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
  *	#define _TASK_STATUS_REQUEST    // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
  *	#define _TASK_WDT_IDS           // Compile with support for wdt control points and task ids
  *	#define _TASK_WDT_IDS           // Compile with support for wdt control points and task ids
  *  #define _TASK_LTS_POINTER       // Compile with support for local task storage pointer
  *  #define _TASK_LTS_POINTER       // Compile with support for local task storage pointer
+ *  #define _TASK_ROLLOVER_FIX		// Compensate for millis() rollover once every 47 days
  */
  */
 
 
 #ifdef _TASK_SLEEP_ON_IDLE_RUN
 #ifdef _TASK_SLEEP_ON_IDLE_RUN
@@ -99,8 +107,18 @@ THE SOFTWARE.
 #include <avr/power.h>
 #include <avr/power.h>
 #endif
 #endif
 
 
+#define TASK_IMMEDIATE			0
+#define TASK_SECOND			1000L
+#define TASK_MINUTE		   60000L
+#define TASK_HOUR		 3600000L
+#define TASK_FOREVER		 (-1)
+#define TASK_ONCE				1
 
 
 #ifdef _TASK_STATUS_REQUEST
 #ifdef _TASK_STATUS_REQUEST
+
+#define	_TASK_SR_NODELAY 	1
+#define	_TASK_SR_DELAY		2
+
 class StatusRequest {
 class StatusRequest {
 	public:
 	public:
 		StatusRequest() {iCount = 0; iStatus = 0; }
 		StatusRequest() {iCount = 0; iStatus = 0; }
@@ -113,7 +131,7 @@ class StatusRequest {
 		
 		
 	private:
 	private:
 		unsigned int	iCount;  // waiting for more that 65000 events seems unreasonable: unsigned int should be sufficient
 		unsigned int	iCount;  // waiting for more that 65000 events seems unreasonable: unsigned int should be sufficient
-		int			iStatus;  // negative = error;  zero = OK; >positive = OK with a specific status
+		int				iStatus;  // negative = error;  zero = OK; >positive = OK with a specific status
 };
 };
 #endif
 #endif
 
 
@@ -123,76 +141,78 @@ class Scheduler;
 class Task {
 class Task {
     friend class Scheduler;
     friend class Scheduler;
     public:
     public:
-	Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, boolean aEnable=false, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);
+		Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, boolean aEnable=false, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);
 #ifdef _TASK_STATUS_REQUEST
 #ifdef _TASK_STATUS_REQUEST
-	Task(void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);
+		Task(void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);
 #endif
 #endif
 
 
-	void enable();
-	bool enableIfNot();
-	void enableDelayed(unsigned long aDelay=0);
-	void delay(unsigned long aDelay=0);
-	void forceNextIteration(); 
-	void restart();
-	void restartDelayed(unsigned long aDelay=0);
-	bool disable();
-	inline bool isEnabled() { return iEnabled; }
-	void set(unsigned long aInterval, long aIterations, void (*aCallback)(),bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);
-	void setInterval(unsigned long aInterval);
-	inline unsigned long getInterval() { return iInterval; }
-	void setIterations(long aIterations);
-	inline long getIterations() { return iIterations; }
-	inline unsigned long getRunCounter() { return iRunCounter; }
-	inline void setCallback(void (*aCallback)()) { iCallback = aCallback; }
-	inline void setOnEnable(bool (*aCallback)()) { iOnEnable = aCallback; }
-	inline void setOnDisable(void (*aCallback)()) { iOnDisable = aCallback; }
+		void enable();
+		bool enableIfNot();
+		void enableDelayed(unsigned long aDelay=0);
+		void delay(unsigned long aDelay=0);
+		void forceNextIteration(); 
+		void restart();
+		void restartDelayed(unsigned long aDelay=0);
+		bool disable();
+		inline bool isEnabled() { return iEnabled; }
+		void set(unsigned long aInterval, long aIterations, void (*aCallback)(),bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);
+		void setInterval(unsigned long aInterval);
+		inline unsigned long getInterval() { return iInterval; }
+		void setIterations(long aIterations);
+		inline long getIterations() { return iIterations; }
+		inline unsigned long getRunCounter() { return iRunCounter; }
+		inline void setCallback(void (*aCallback)()) { iCallback = aCallback; }
+		inline void setOnEnable(bool (*aCallback)()) { iOnEnable = aCallback; }
+		inline void setOnDisable(void (*aCallback)()) { iOnDisable = aCallback; }
 #ifdef _TASK_TIMECRITICAL
 #ifdef _TASK_TIMECRITICAL
-	inline long getOverrun() { return iOverrun; }
+		inline long getOverrun() { return iOverrun; }
 #endif
 #endif
-	inline bool isFirstIteration() { return (iRunCounter <= 1); } 
-	inline bool isLastIteration() { return (iIterations == 0); }
+		inline bool isFirstIteration() { return (iRunCounter <= 1); } 
+		inline bool isLastIteration() { return (iIterations == 0); }
 #ifdef _TASK_STATUS_REQUEST
 #ifdef _TASK_STATUS_REQUEST
-	void waitFor(StatusRequest* aStatusRequest);
-	inline StatusRequest* getStatusRequest() {return iStatusRequest; }
+		void waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
+		void waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
+		inline StatusRequest* getStatusRequest() {return iStatusRequest; }
 #endif
 #endif
 #ifdef _TASK_WDT_IDS
 #ifdef _TASK_WDT_IDS
-	inline void setId(unsigned int aID) { iTaskID = aID; }
-	inline unsigned int getId() { return iTaskID; }
-	inline void setControlPoint(unsigned int aPoint) { iControlPoint = aPoint; }
-	inline unsigned int getControlPoint() { return iControlPoint; }
+		inline void setId(unsigned int aID) { iTaskID = aID; }
+		inline unsigned int getId() { return iTaskID; }
+		inline void setControlPoint(unsigned int aPoint) { iControlPoint = aPoint; }
+		inline unsigned int getControlPoint() { return iControlPoint; }
 #endif
 #endif
 #ifdef _TASK_LTS_POINTER
 #ifdef _TASK_LTS_POINTER
-	inline void	setLtsPointer(void *aPtr) { iLTS = aPtr; }
-	inline void* getLtsPointer() { return iLTS; }
+		inline void	setLtsPointer(void *aPtr) { iLTS = aPtr; }
+		inline void* getLtsPointer() { return iLTS; }
 #endif
 #endif
 	
 	
     private:
     private:
-	void reset();
+		void reset();
 
 
-    volatile bool			iEnabled;
-	bool					iInOnEnable;
-    volatile unsigned long	iInterval;
-	volatile unsigned long	iPreviousMillis;
+		volatile bool			iEnabled;
+		volatile bool			iInOnEnable;
+		volatile unsigned long	iInterval;
+		volatile unsigned long	iPreviousMillis;
 #ifdef _TASK_TIMECRITICAL
 #ifdef _TASK_TIMECRITICAL
-	volatile long			iOverrun; 
+		volatile long			iOverrun; 
 #endif
 #endif
-	volatile long			iIterations;
-	long					iSetIterations; 
-	unsigned long			iRunCounter;
-	void					(*iCallback)();
-	bool					(*iOnEnable)();
-	void					(*iOnDisable)();
-	Task					*iPrev, *iNext;
-	Scheduler				*iScheduler;
+		volatile long			iIterations;
+		long					iSetIterations; 
+		unsigned long			iRunCounter;
+		void					(*iCallback)();
+		bool					(*iOnEnable)();
+		void					(*iOnDisable)();
+		Task					*iPrev, *iNext;
+		Scheduler				*iScheduler;
 #ifdef _TASK_STATUS_REQUEST
 #ifdef _TASK_STATUS_REQUEST
-	StatusRequest			*iStatusRequest;
+		StatusRequest			*iStatusRequest;
+		byte					iWaiting;
 #endif
 #endif
 #ifdef _TASK_WDT_IDS
 #ifdef _TASK_WDT_IDS
-	unsigned int			iTaskID;
-	unsigned int			iControlPoint;
+		unsigned int			iTaskID;
+		unsigned int			iControlPoint;
 #endif
 #endif
 #ifdef _TASK_LTS_POINTER
 #ifdef _TASK_LTS_POINTER
-	void					*iLTS;
+		void					*iLTS;
 #endif
 #endif
 };
 };
 
 
@@ -213,6 +233,9 @@ class Scheduler {
 #ifdef _TASK_LTS_POINTER
 #ifdef _TASK_LTS_POINTER
 		inline void* currentLts() {return iCurrent->iLTS; }
 		inline void* currentLts() {return iCurrent->iLTS; }
 #endif
 #endif
+#ifdef _TASK_TIMECRITICAL
+		inline bool isOverrun() { return (iCurrent->iOverrun < 0); }
+#endif
 
 
 	private:
 	private:
 		Task	*iFirst, *iLast, *iCurrent;
 		Task	*iFirst, *iLast, *iCurrent;
@@ -282,14 +305,23 @@ void StatusRequest::signalComplete(int aStatus) {
  *  @param: aStatusRequest - a pointer for the StatusRequest to wait for.
  *  @param: aStatusRequest - a pointer for the StatusRequest to wait for.
  *  If aStatusRequest is NULL, request for waiting is ignored, and the waiting task is not enabled. 
  *  If aStatusRequest is NULL, request for waiting is ignored, and the waiting task is not enabled. 
  */
  */
-void Task::waitFor(StatusRequest* aStatusRequest) {
+void Task::waitFor(StatusRequest* aStatusRequest, unsigned long aInterval, long aIterations) {
 	if ( ( iStatusRequest = aStatusRequest) ) { // assign internal StatusRequest var and check if it is not NULL
 	if ( ( iStatusRequest = aStatusRequest) ) { // assign internal StatusRequest var and check if it is not NULL
-		setIterations(1);
-		setInterval(0); 
+		setIterations(aIterations);
+		setInterval(aInterval); 
+		iWaiting = _TASK_SR_NODELAY;  // no delay
 		enable();
 		enable();
 	}
 	}
 }
 }
 
 
+void Task::waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval, long aIterations) {
+	if ( ( iStatusRequest = aStatusRequest) ) { // assign internal StatusRequest var and check if it is not NULL
+		setIterations(aIterations);
+		if ( aInterval ) setInterval(aInterval);  // For the dealyed version only set the interval if it was not a zero
+		iWaiting = _TASK_SR_DELAY;  // with delay equal to the current interval
+		enable();
+	}
+}
 #endif
 #endif
 
 
 /** Resets (initializes) the task/
 /** Resets (initializes) the task/
@@ -312,6 +344,9 @@ void Task::reset() {
 #ifdef _TASK_LTS_POINTER
 #ifdef _TASK_LTS_POINTER
 	iLTS = NULL;
 	iLTS = NULL;
 #endif
 #endif
+#ifdef _TASK_STATUS_REQUEST
+	iWaiting = 0;
+#endif
 }
 }
 
 
 /** Explicitly set Task execution parameters
 /** Explicitly set Task execution parameters
@@ -533,6 +568,7 @@ void Scheduler::execute() {
 #ifdef _TASK_SLEEP_ON_IDLE_RUN
 #ifdef _TASK_SLEEP_ON_IDLE_RUN
 	bool		idleRun = true;
 	bool		idleRun = true;
 #endif
 #endif
+	unsigned long targetMillis;
 	
 	
 	iCurrent = iFirst;
 	iCurrent = iFirst;
 
 
@@ -540,50 +576,59 @@ void Scheduler::execute() {
 		do {   		
 		do {   		
 			if (iCurrent->iEnabled) {
 			if (iCurrent->iEnabled) {
 	#ifdef _TASK_WDT_IDS
 	#ifdef _TASK_WDT_IDS
-	// For each task the control points are initialized to avoid confusion because of carry-over
+	// For each task the control points are initialized to avoid confusion because of carry-over:
 				iCurrent->iControlPoint = 0;
 				iCurrent->iControlPoint = 0;
 	#endif
 	#endif
+	
+	// Disable task on last iteration:
 				if (iCurrent->iIterations == 0) {
 				if (iCurrent->iIterations == 0) {
 					iCurrent->disable();
 					iCurrent->disable();
 					break;
 					break;
 				}
 				}
 	#ifdef  _TASK_STATUS_REQUEST
 	#ifdef  _TASK_STATUS_REQUEST
-	// If StatusRequest object was provided (not NULL) and it is still bending, this task should not run
-	// Otherwise, continue with execution as usual.  Tasks waiting to StatusRequest usually have  interval = 0, and iterations = 1
-	// so they will run once immediately. 
-				if ( iCurrent->iStatusRequest && (iCurrent->iStatusRequest)->pending() ) break;
+	// If StatusRequest object was provided, and still pending, and task is waiting, this task should not run
+	// Otherwise, continue with execution as usual.  Tasks waiting to StatusRequest need to be rescheduled according to 
+	// how they were placed into waiting state (waitFor or waitForDelayed)
+				if ( iCurrent->iWaiting ) {
+					if ( (iCurrent->iStatusRequest)->pending() ) break;
+					iCurrent->iPreviousMillis = (iCurrent->iWaiting == _TASK_SR_NODELAY) ? millis()-iCurrent->iInterval : millis();
+					iCurrent->iWaiting = 0;
+				}
 	#endif
 	#endif
-				if ( iCurrent->iInterval > 0 ) {
-					unsigned long targetMillis = iCurrent->iPreviousMillis + iCurrent->iInterval;
-					if ( targetMillis <= millis() ) {
-						if ( iCurrent->iIterations > 0 ) iCurrent->iIterations--;  // do not decrement (-1) being a signal of eternal task
-						iCurrent->iRunCounter++;
-						iCurrent->iPreviousMillis += iCurrent->iInterval;
-
+	// Determine when current task is supposed to run
+	// Once every 47 days there is a rollover execution which will occur due to millis and targetMillis rollovers
+	// That is why there is an option to compile with rollover fix
+	// Example
+	//	iPreviousMillis = 65000
+	//	iInterval = 600
+	//	millis() = 65500
+	//  targetMillis = 65000 + 600 = (should be 65600) 65 (due to rollover)
+	//	so 65 < 65500. should be 65600 > 65500. - task will be scheduled incorrectly
+	//  since targetMillis (65) < iPreviousMillis (65000), rollover fix kicks in:
+	//  iPreviousMillis(65000) > millis(65500) - iInterval(600) = 64900 - task will not be scheduled
+	
+				targetMillis = iCurrent->iPreviousMillis + iCurrent->iInterval;
+	#ifdef _TASK_ROLLOVER_FIX
+				if ( targetMillis < iCurrent->iPreviousMillis ) {  // targetMillis rolled over!
+					if ( iCurrent->iPreviousMillis > ( millis() - iCurrent->iInterval) )  break;
+				}
+				else
+	#endif
+					if ( targetMillis > millis() ) break;
+	
+				iCurrent->iPreviousMillis = targetMillis;
 	#ifdef _TASK_TIMECRITICAL
 	#ifdef _TASK_TIMECRITICAL
-	// Updated_previous+current should put us into the future, so iOverrun should be positive or zero. 
+	// Updated_previous+current interval should put us into the future, so iOverrun should be positive or zero. 
 	// If negative - the task is behind (next execution time is already in the past) 
 	// If negative - the task is behind (next execution time is already in the past) 
-						iCurrent->iOverrun = (long) (iCurrent->iPreviousMillis + iCurrent->iInterval - millis());
+				iCurrent->iOverrun = (long) (iCurrent->iPreviousMillis + iCurrent->iInterval - millis());
 	#endif
 	#endif
-
-						if ( iCurrent->iCallback ) {
-							( *(iCurrent->iCallback) )();
-	#ifdef _TASK_SLEEP_ON_IDLE_RUN
-							idleRun = false;
-	#endif
-						}
-						break;
-					}
-				}
-				else {
-					if ( iCurrent->iIterations > 0 ) iCurrent->iIterations--;  // do not decrement (-1) being a signal of eternal task
-					iCurrent->iRunCounter++;
-					if ( iCurrent->iCallback ) {
-						( *(iCurrent->iCallback) )();
+				if ( iCurrent->iIterations > 0 ) iCurrent->iIterations--;  // do not decrement (-1) being a signal of never-ending task
+				iCurrent->iRunCounter++;
+				if ( iCurrent->iCallback ) {
+					( *(iCurrent->iCallback) )();
 	#ifdef _TASK_SLEEP_ON_IDLE_RUN
 	#ifdef _TASK_SLEEP_ON_IDLE_RUN
-						idleRun = false;
+					idleRun = false;
 	#endif
 	#endif
-					}
 				}
 				}
 			}
 			}
 		} while (0); //guaranteed single run - allows use of "break" to exit 
 		} while (0); //guaranteed single run - allows use of "break" to exit