Last active
March 15, 2016 12:08
-
-
Save atrakeur/9041da2d10c2d0fd7589 to your computer and use it in GitHub Desktop.
Arduino brain interfaces. See https://www.atrakeur.com/blog/art33-programmation_modulaire_et_multitaches_avec_arduino for more details
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Origo.h" | |
#include "Brain.h" | |
int Brain::addModule(AbstractBrain * module) | |
{ | |
DEBUG_PRINT("Brain: Adding module "); | |
DEBUG_PRINT(module->getName()); | |
DEBUG_PRINT("\n"); | |
BrainConfig* freeConfig = getFreeModuleConfig(); | |
if (freeConfig == nullptr) { | |
DEBUG_PRINT("Brain: No more modules slots\n"); | |
return BRAIN_ERROR_NO_MODULES; | |
} | |
freeConfig->enabled = true; | |
freeConfig->module = module; | |
return BRAIN_OK; | |
} | |
int Brain::removeModule(AbstractBrain * module) | |
{ | |
DEBUG_PRINT("Brain: Removing module "); | |
DEBUG_PRINT(module->getName()); | |
DEBUG_PRINT(""); | |
BrainConfig* config = getModuleConfig(module); | |
config->enabled = false; | |
config->module = nullptr; | |
return BRAIN_OK; | |
} | |
void Brain::initialize() | |
{ | |
DEBUG_PRINT("Brain: Initializing modules \n"); | |
for (int i = 0; i < BRAIN_MAX_MODULES; i++) { | |
if (configs[i].enabled) { | |
DEBUG_PRINT("\tBrain: Initializing module "); | |
DEBUG_PRINT(configs[i].module->getName()); | |
DEBUG_PRINT("\n"); | |
configs[i].module->initialize(); | |
} | |
} | |
} | |
void Brain::tick() | |
{ | |
//Run module code | |
if (configs[nextModule].enabled && configs[nextModule].isDue()) { | |
executeModule(&configs[nextModule]); | |
} | |
//Jump to the next module available | |
for (int i = 1; i < BRAIN_MAX_MODULES; i++) { | |
int index = (nextModule + i) % BRAIN_MAX_MODULES; | |
if (configs[index].enabled && configs[index].isDue()) { | |
nextModule = index; | |
break; | |
} | |
} | |
} | |
void Brain::printModule(AbstractBrain * module, Print * output) | |
{ | |
BrainConfig* moduleConfig = getModuleConfig(module); | |
if (moduleConfig == nullptr) { | |
return; | |
} | |
output->print("Brain: "); | |
output->print("\t\t"); | |
output->print(moduleConfig->module->getName()); | |
output->print("\t\t"); | |
} | |
void Brain::printModules(Print * output) | |
{ | |
output->print("Brain: "); | |
output->print("\t\t"); | |
output->print("Name"); | |
output->print("\t\t\t"); | |
output->print("Run time"); | |
output->print("\t"); | |
output->print("Late Time"); | |
output->print("\n"); | |
for (int i = 0; i < BRAIN_MAX_MODULES; i++) { | |
if (configs[i].enabled) { | |
printModule(configs[i].module, output); | |
} | |
} | |
output->print("\n"); | |
} | |
BrainConfig * Brain::getModuleConfig(AbstractBrain * module) | |
{ | |
for (int i = 0; i < BRAIN_MAX_MODULES; i++) { | |
if (configs[i].enabled && configs[i].module == module) { | |
return &configs[i]; | |
} | |
} | |
return nullptr; | |
} | |
BrainConfig * Brain::getFreeModuleConfig() | |
{ | |
for (int i = 0; i < BRAIN_MAX_MODULES; i++) { | |
if (!configs[i].enabled) { | |
return &configs[i]; | |
} | |
} | |
return nullptr; | |
} | |
void Brain::executeModule(BrainConfig * config) | |
{ | |
actualModule = config; | |
int retVal = config->module->tick(); | |
config->lastRunTime = millis(); | |
config->timeInterval = retVal; | |
actualModule = nullptr; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define BRAIN_MAX_MODULES 4 | |
#define BRAIN_OK 0 | |
#define BRAIN_ERROR_NO_MODULES -1 | |
/** | |
* Define a structure that old information for a given Brain module | |
*/ | |
typedef struct BrainConfig { | |
boolean enabled; | |
AbstractBrain* module; | |
unsigned long lastRunTime; | |
int timeInterval; | |
inline bool isDue() { | |
return (unsigned long)(millis() - lastRunTime) >= timeInterval; | |
} | |
}; | |
/** | |
* The main Brain class | |
*/ | |
class Brain { | |
private: | |
int nextModule; | |
int moduleCount; | |
BrainConfig* actualModule; | |
BrainConfig configs[BRAIN_MAX_MODULES]; | |
public: | |
int addModule(AbstractBrain* module); | |
int removeModule(AbstractBrain* module); | |
void initialize(); | |
void tick(); | |
void printModule(AbstractBrain* module, Print* output); | |
void printModules(Print* output); | |
protected: | |
BrainConfig* getModuleConfig(AbstractBrain* module); | |
BrainConfig* getFreeModuleConfig(); | |
void executeModule(BrainConfig * config); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Defines a Brain module | |
*/ | |
class AbstractBrain { | |
public: | |
/* The name of the module */ | |
virtual char* getName() = 0; | |
/* Initialize the module */ | |
virtual void initialize() = 0; | |
/* Run the module code */ | |
virtual int tick() = 0; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "BrainModule.h" | |
#include "StatusLed.h" | |
char * StatusLed::getName() | |
{ | |
return "Status Led"; | |
} | |
void StatusLed::initialize() | |
{ | |
blinkFreq = 1000; | |
pinMode(13, OUTPUT); | |
} | |
int StatusLed::tick() | |
{ | |
isOn = !isOn; | |
if (isOn) { | |
digitalWrite(13, HIGH); | |
} | |
else { | |
digitalWrite(13, LOW); | |
} | |
return blinkFreq; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "BrainModules.h" | |
/** | |
* Define a module that just blink a led | |
*/ | |
class StatusLed : public AbstractBrain { | |
private: | |
bool isOn; | |
int blinkFreq; | |
public: | |
char* getName(); | |
void initialize(); | |
int tick(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Brain.h" | |
#include "StatusLed.h" | |
Brain brain; //Create Brain instance | |
StatusLed status; //Create instance of StatusLed BrainModule | |
void setup() { | |
Serial.begin(19200); while (!Serial); //Init serial and wait for it (for leonardo) | |
Serial.println("Setup: Configuring brain modules"); | |
brain.addModule(&status); //Register the module to the Brain | |
Serial.println("Setup: Initializing brain modules"); | |
brain.initialize(); //Initialize all registered modules | |
Serial.println("Setup: starting done"); | |
} | |
void loop() { | |
brain.tick(); //Take care of executing all modules | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment