Very simple cooperative round-robin task scheduler. See examples.

Revision:
1:f043501c4bed
Child:
3:95ec5c83c2fe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Examples/example4.h	Fri Mar 04 12:15:38 2011 +0000
@@ -0,0 +1,168 @@
+/*
+    Copyright (c) 2011 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+    
+    @file          example4.h 
+    @purpose       Simple round-robin cooperative scheduler example
+    @date          Mar 2011
+    @author        Andy Kirkham
+*/
+
+/*
+    This example uses the network stack to setup the time. Note, when I tested
+    this I had two things in place. If you want to run this example then you too
+    will need:-
+    
+        1. Your Mbed with an Ethernet jack socket. I used a Cool Components Workshop
+           board: http://www.coolcomponents.co.uk/catalog/product_info.php?products_id=528
+        2. You will need to import a network stack into your project. The one I used was
+           this one: http://mbed.org/users/segundo/libraries/NetServices/ljhqix
+           
+    What this example shows is the usual "flash some LEDs tasks" and an example of how
+    to setup the time on the Mbed via the attached ethernet/Internet network. I used
+    setting the time as a network example but you could do HTTP requests, etc.
+    
+    The purpose of this example is to show how to use the network stack to do a NON-BLOCKING
+    network call. SimpleScheduler is a coopertive scheduler and that means you should not
+    wait around in task functions. You should complete your tasks as fast as possible so
+    that other scheduled tasks are not blocked from running. However, making network calls
+    generally take some time to complete so are considered "slow" (compared the clock freq
+    of the LPC1768 micro that is!). So to avoid stalling out waiting for a reply our tasks
+    must use NON-BLOCKING calls. This is what this example is for, to demostrate how to
+    make a non-blocking network stack call.
+*/
+
+#include "mbed.h"
+#include "SimpleScheduler.h"
+#include "EthernetNetIf.h"
+#include "HTTPClient.h"
+#include "NTPClient.h"
+
+// Setup a serial port to print the time to.
+Serial pc(USBTX, USBRX);
+
+// The usual suspects.
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+// A scheduler.
+SimpleScheduler *scheduler;
+
+// Setup the network statck.
+EthernetNetIf  eth;
+EthernetErr ethErr;
+NTPClient ntp;
+NTPResult result;
+
+// Declare the host we are going to ask the time.
+Host server(IpAddr(), 123, "0.de.pool.ntp.org");
+
+// Scheduler task functions.
+void f2(SimpleTask *task) { led2 = !led2; }
+void f3(SimpleTask *task) { led3 = !led3; }
+void f4(SimpleTask *task) { led4 = !led4; }
+void netPoll(SimpleTask *task) { Net::poll(); }
+
+bool clockAccurate;
+
+// Scheduler task function.
+void showTime(SimpleTask *task) {
+    time_t theTime = time(NULL);
+    char *s = ctime(&theTime);
+    for(char *p = s; *p != '\0'; p++) if (*p == '\n') { *p = '\0'; break; } // rtrim \n
+    pc.printf("Time is now (UTC): %s", s);
+    if (!clockAccurate) {
+        pc.printf(" (maybe inaccurate)");
+    }
+    pc.printf("\n");
+    if (result != NTP_OK) {
+        pc.printf(" NTP status: ");
+        switch(result) {
+            case NTP_PROCESSING: pc.printf("NTP_PROCESSING.\n"); break;
+            case NTP_PRTCL:      pc.printf("NTP_PRTCL protocol error.\n"); break;
+            case NTP_TIMEOUT:    pc.printf("NTP_TIMEOUT.\n"); break;
+            case NTP_DNS :       pc.printf("NTP_DNS.\n"); break;
+        }
+    }
+}
+
+// Network stack callbacks.
+void getTimeCallback(NTPResult i) { 
+    result = i; 
+    led1 = !led1;
+    clockAccurate = i == NTP_OK ? true : false;
+}
+
+// Scheduler task function.
+void setTime(SimpleTask *task) {
+    if (!ethErr) {
+        result = NTP_PROCESSING;
+        ntp.setTime(server, getTimeCallback);            
+    }
+}
+
+int main() {
+    pc.baud(115200);
+    pc.printf("Example3 starting up.\n");
+    
+    clockAccurate = false;
+    
+    ethErr = eth.setup();
+    if (ethErr) {
+        pc.printf("Error %d in setup.\n", ethErr);
+    }
+    else {
+        result = NTP_PROCESSING;
+        ntp.setTime(server, getTimeCallback);        
+    }
+    
+    scheduler = new SimpleScheduler;
+    
+    scheduler
+        ->addTask( new SimpleTask(200, f2) )
+        ->addTask( new SimpleTask(300, f3) )
+        ->addTask( new SimpleTask(0.4, f4) )
+    ;
+    
+    // Only add these tasks if Ethernet setup is ok.
+    // Notice we add netPoll() with a time of zero. 
+    // Zero means "call as often as possible". The
+    // network stack needs to be polled on a regular 
+    // basis. As often as possible in fact. The other
+    // two tasks are "just print the time to serial
+    // once every 5seconds" and the other is "update
+    // the clock from remote host once an hour".
+    // Remember, integers are milliseconds but real
+    // numbers are seconds).
+    if (!ethErr) {
+        scheduler
+            ->addTask( new SimpleTask(0,   netPoll) )
+            ->addTask( new SimpleTask(5.0, showTime) )
+            ->addTask( new SimpleTask(3600.0, setTime) )
+        ;         
+    }
+    
+    scheduler->run();    
+}
+
+
+