Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nrwiersma committed Sep 2, 2016
0 parents commit b84e6f7
Show file tree
Hide file tree
Showing 9 changed files with 352 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015 Nicholas Wiersma

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.
90 changes: 90 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# ESP8266Scheduler

ESP8266 Co-operative Multitasking

# Quick Start

## Installing

You can install through the Arduino Library Manager. The package name is
**ESP8266Scheduler**.

## Usage

Include the library in your sketch

```cpp
#include <Scheduler.h>
```

In your setup function start the scheduler

```cpp
Scheduler.start(&task);

Scheduler.begin();
```

The scheduler blocks once begun, so the loop function is never called. You should instead create tasks.

# Creating a Task

Tasks are classes that should inherit the ```Task``` class. A task can define a ```loop()``` and ```setup()``` function
much as the normal Arduino standard.

```cpp
class BlinkTask : public Task {
protected:
void setup() {
state = HIGH;

pinMode(2, OUTPUT);
pinMode(2, state);
}

void loop() {
state = state == HIGH ? LOW : HIGH;
pinMode(2, state);

delay(1000);
}

private:
uint8_t state;
} blink_task;
```

**IMPORTANT: Tasks must be declared globally on the stack (not a pointer). Failure to do so will crash your device.**

### Advanced Task Functions

The ```Task``` also exposes a ```bool shouldRun()``` method that is used determine if the task loop
should be be resumed. This can be inherited to add your own logic to determine if your code should be resumed.

```cpp
bool shouldRun() {
bool run = Task::shouldRun();

// Your code here

return run;
}
```

**This function handles the ```delay()``` logic. The parent method should be called.**

# Documentation

## Methods

### start
```
static void start(Task *task)
```
> Adds a task to the multitasking queue.
### begin
```
static void begin()
```
> Starts the scheduler. This function is "blocking". It should be the last call the ```setup``` function.
62 changes: 62 additions & 0 deletions examples/simple.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <Arduino.h>
#include <Scheduler.h>

class PrintTask : public Task {
protected:
void loop() {
Serial.println("Print Loop Start");

delay(5000);

Serial.println("Print Loop End");

delay(5000);
}
} print_task;

class BlinkTask : public Task {
protected:
void setup() {
state = HIGH;

pinMode(2, OUTPUT);
pinMode(2, state);
}

void loop() {
state = state == HIGH ? LOW : HIGH;
pinMode(2, state);

delay(1000);
}

private:
uint8_t state;
} blink_task;

class MemTask : public Task {
public:
void loop() {
Serial.print("Free Heap: ");
Serial.print(ESP.getFreeHeap());
Serial.println(" bytes");

delay(10000);
}
} mem_task;

void setup() {
Serial.begin(115200);

Serial.println("");

delay(1000);

Scheduler.start(&print_task);
Scheduler.start(&blink_task);
Scheduler.start(&mem_task);

Scheduler.begin();
}

void loop() {}
22 changes: 22 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#######################################
# Syntax Coloring Map For ESP8266Scheduler
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

Scheduler KEYWORD1
Task KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################
start KEYWORD2
begin KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################

# LITERAL1
13 changes: 13 additions & 0 deletions library.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "ESP8266Scheduler",
"keywords": "multitasking",
"description": "ESP8266 Co-operative Multitasking",
"repository":
{
"type": "git",
"url": "https://github.com/nrwiersma/ESP8266Scheduler.git"
},
"frameworks": "arduino",
"platforms": "espressif",
"version": "0.1"
}
9 changes: 9 additions & 0 deletions library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=ESP8266Scheduler
version=0.1
author=Nick Wiersma <[email protected]>
maintainer=Nick Wiersma <[email protected]>
sentence=ESP8266 Co-operative Multitasking
paragraph=Co-operative multitasking for ESP8266 modules.
category=Other
url=https://github.com/nrwiersma/ESP8266Scheduler.git
architectures=esp8266
40 changes: 40 additions & 0 deletions src/Scheduler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "Scheduler.h"

extern "C" {
#include "cont.h"

void yield();
}

SchedulerClass Scheduler;

Task SchedulerClass::main;
Task *SchedulerClass::current = &SchedulerClass::main;

SchedulerClass::SchedulerClass() {
main.next = &main;
main.prev = &main;
}

void SchedulerClass::start(Task *task) {
task->next = &main;
task->prev = main.prev;

main.prev->next = task;
main.prev = task;
}

void SchedulerClass::begin() {
while (1) {
if (current->shouldRun())
cont_run(&current->context, task_tramponline);

yield();

current = current->next;
}
}

void task_tramponline() {
SchedulerClass::current->loopWrapper();
}
29 changes: 29 additions & 0 deletions src/Scheduler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef SCHEDULER_H
#define SCHEDULER_H

// #include <Arduino.h>
#include "Task.h"

extern "C" void loop();
extern void task_tramponline();

class SchedulerClass {
public:
SchedulerClass();

static void start(Task *task);

static void begin();

private:
friend void task_tramponline();

// class MainTask : public Task {};

static Task main;
static Task *current;
};

extern SchedulerClass Scheduler;

#endif
66 changes: 66 additions & 0 deletions src/Task.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef TASK_H
#define TASK_H

#include <Arduino.h>
#include "Scheduler.h"

extern "C" {
#include "cont.h"
}

class Task {
public:
Task() {
cont_init(&context);
}

protected:
virtual void setup() {}

virtual void loop() {}

void delay(unsigned long ms) {
if (ms) {
delay_time = millis();
delay_ms = ms;
}

yield();
}

void yield() {
cont_yield(&context);
}

virtual bool shouldRun() {
unsigned long now = millis();

return !delay_ms || now >= delay_time + delay_ms;
}

private:
friend class SchedulerClass;
friend void task_tramponline();

Task *next;
Task *prev;
cont_t context;

bool setup_done = false;
unsigned long delay_time;
unsigned long delay_ms;

void loopWrapper() {
if (!setup_done) {
setup();
setup_done = true;
}

while(1) {
loop();
yield();
}
}
};

#endif

0 comments on commit b84e6f7

Please sign in to comment.