diff --git a/306-controller_interface.X/middleware/alive_checker.c b/306-controller_interface.X/middleware/alive_checker.c new file mode 100644 index 0000000..b674c28 --- /dev/null +++ b/306-controller_interface.X/middleware/alive_checker.c @@ -0,0 +1,176 @@ +/** + * @author Rémi Heredero + * @version 1.0.0 + * @date August 2023 + * @file alive_checker.c + */ + +#include "alive_checker.h" + +void ALIVE_CHECKER_init(ALIVE_CHECKER* me){ + me->state = STAC_INIT; + me->isAlive = false; + me->aliveTime = 10; + me->setup.f = NULL; + me->born.f = NULL; + me->wait.f = NULL; + me->dead.f = NULL; +} + +void ALIVE_CHECKER_startBehaviour(ALIVE_CHECKER* me){ + POST(me, &ALIVE_CHECKER_processEvent, evACinit, 0, 0); +} + +bool ALIVE_CHECKER_processEvent(Event* ev) { + bool processed = false; + ALIVE_CHECKER* me = (ALIVE_CHECKER*)Event_getTarget(ev); + ALIVE_CHECKER_STATES oldState = me->state; + evIDT evid = Event_getId(ev); + uint64_t data = Event_getData(ev); + + switch (me->state) { // onState + case STAC_INIT: + if (ev->id == evACinit) { + me->state = STAC_SETUP; + } + break; + + case STAC_SETUP: + if (ev->id = evACborn) { + me->state = STAC_BORN; + } + break; + + case STAC_BORN: + if (ev->id = evACready) { + me->state = STAC_WAIT; + ALIVE_CHECKER_emitPoll(me, me->aliveTime*10, 0); + } + break; + + case STAC_WAIT: + if (ev->id = evACpoll) { + if (me->isAlive) { + me->state = STAC_WAIT; + ALIVE_CHECKER_emitPoll(me, me->aliveTime*10, 0); + } else { + me->state = STAC_DEAD; + } + } + break; + + case STAC_DEAD: + if(ev->id = evACborn) { + me->state = STAC_BORN; + } + break; + } + + if(oldState != me->state){ + switch (oldState) { // onExit + case STAC_INIT: + break; + + case STAC_SETUP: + break; + + case STAC_BORN: + break; + + case STAC_WAIT: + break; + + case STAC_DEAD: + break; + } + + switch (me->state) { // onEntry + case STAC_INIT: + break; + + case STAC_SETUP: + if (me->setup.f != NULL) { + me->setup.f(me->setup.p); + } + break; + + case STAC_BORN: + if (me->born.f != NULL) { + me->born.f(me->born.p); + } + break; + + case STAC_WAIT: + me->isAlive = false; + if (me->wait.f != NULL) { + me->wait.f(me->wait.p); + } + break; + + case STAC_DEAD: + if (me->dead.f != NULL) { + me->dead.f(me->dead.p); + } + break; + } + + processed = true; + } + return processed; +} + +/************* + * Callbacks * + *************/ + +void ALIVE_CHECKER_onSetup(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p) { + me->setup.f = f; + me->setup.p = p; +} + +void ALIVE_CHECKER_onBorn(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p) { + me->born.f = f; + me->born.p = p; +} + +void ALIVE_CHECKER_onWait(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p) { + me->wait.f = f; + me->wait.p = p; +} + +void ALIVE_CHECKER_onDead(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p) { + me->dead.f = f; + me->dead.p = p; +} + +/************ + * EMITTERS * + ************/ + +void ALIVE_CHECKER_emitBorn(ALIVE_CHECKER* me, uint16_t t, int64_t data) { + POST(me, &ALIVE_CHECKER_processEvent, evACborn, t, data); +} + +void ALIVE_CHECKER_emitReady(ALIVE_CHECKER* me, uint16_t t, int64_t data) { + POST(me, &ALIVE_CHECKER_processEvent, evACready, t, data); +} + +void ALIVE_CHECKER_emitPoll(ALIVE_CHECKER* me, uint16_t t, int64_t data) { + POST(me, &ALIVE_CHECKER_processEvent, evACpoll, t, data); +} + +/*********** + * SETTERS * + ***********/ + +void ALIVE_CHECKER_setAliveTime(ALIVE_CHECKER* me, uint8_t v) { + me->aliveTime = v; +} + +void ALIVE_CHECKER_setIsAlive(ALIVE_CHECKER* me, bool v) { + me->aliveTime = v; +} + +void ALIVE_CHECKER_ISALIVE(ALIVE_CHECKER* me) { + ALIVE_CHECKER_setIsAlive(me, true); +} diff --git a/306-controller_interface.X/middleware/alive_checker.h b/306-controller_interface.X/middleware/alive_checker.h new file mode 100644 index 0000000..aeecb85 --- /dev/null +++ b/306-controller_interface.X/middleware/alive_checker.h @@ -0,0 +1,134 @@ +/** + * @author Rémi Heredero + * @version 1.0.0 + * @date August 2023 + * @file alive_checker.h + */ +#ifndef ALIVE_CHECKER_H +#define ALIVE_CHECKER_H + +#include "../xf/xf.h" + +typedef enum { + STAC_INIT, + STAC_SETUP, + STAC_BORN, + STAC_WAIT, + STAC_DEAD +} ALIVE_CHECKER_STATES; + +typedef enum { + evACinit = 100, // TODO change this number (< 256) + evACborn, + evACready, + evACpoll +} ALIVE_CHECKER_EVENTS; + +typedef void (*ALIVE_CHECKER_CALLBACK_FUNCTION)(void*); +typedef struct { + ALIVE_CHECKER_CALLBACK_FUNCTION f; // function + void* p; // param(s) +} ALIVE_CHECKER_CALLBACK; + +typedef struct { + ALIVE_CHECKER_STATES state; + bool isAlive; + uint8_t aliveTime; + ALIVE_CHECKER_CALLBACK setup; + ALIVE_CHECKER_CALLBACK born; + ALIVE_CHECKER_CALLBACK wait; + ALIVE_CHECKER_CALLBACK dead; +} ALIVE_CHECKER; + +/** + * Initialize the ALIVE_CHECKER + * @param me the ALIVE_CHECKER itself + */ +void ALIVE_CHECKER_init(ALIVE_CHECKER* me); + +/** + * Start the ALIVE_CHECKER state machine + * @param me the ALIVE_CHECKER itself + */ +void ALIVE_CHECKER_startBehaviour(ALIVE_CHECKER* me); + +/** + * Process the event + * @param ev the event to process + * @return true if the event is processed + */ +bool ALIVE_CHECKER_processEvent(Event* ev); + +/************* + * Callbacks * + *************/ + +/** + * Set the callback function to call when the ALIVE_CHECKER is entering state setup + * @param me the ALIVE_CHECKER itself + * @param f the function to call + * @param p the param(s) to pass to the function + */ +void ALIVE_CHECKER_onSetup(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p); + +/** + * Set the callback function to call when the ALIVE_CHECKER is entering state born + * @param me the ALIVE_CHECKER itself + * @param f the function to call + * @param p the param(s) to pass to the function + */ +void ALIVE_CHECKER_onBorn(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p); + +/** + * Set the callback function to call when the ALIVE_CHECKER is entering state wait + * @param me the ALIVE_CHECKER itself + * @param f the function to call + * @param p the param(s) to pass to the function + */ +void ALIVE_CHECKER_onWait(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p); + +/** + * Set the callback function to call when the ALIVE_CHECKER is entering state dead + * @param me the ALIVE_CHECKER itself + * @param f the function to call + * @param p the param(s) to pass to the function + */ +void ALIVE_CHECKER_onDead(ALIVE_CHECKER* me, ALIVE_CHECKER_CALLBACK_FUNCTION f, void* p); + +/************ + * EMITTERS * + ************/ + +/** + * Emit the born event + * @param me the ALIVE_CHECKER itself + * @param t time to wait in ms before triggering event + * @param data data to put on the event for XF + */ +void ALIVE_CHECKER_emitBorn(ALIVE_CHECKER* me, uint16_t t, int64_t data); + +/** + * Emit the ready event + * @param me the ALIVE_CHECKER itself + * @param t time to wait in ms before triggering event + * @param data data to put on the event for XF + */ +void ALIVE_CHECKER_emitReady(ALIVE_CHECKER* me, uint16_t t, int64_t data); + +/** + * Emit the poll event + * @param me the ALIVE_CHECKER itself + * @param t time to wait in ms before triggering event + * @param data data to put on the event for XF + */ +void ALIVE_CHECKER_emitPoll(ALIVE_CHECKER* me, uint16_t t, int64_t data); + +/*********** + * SETTERS * + ***********/ + +void ALIVE_CHECKER_setAliveTime(ALIVE_CHECKER* me, uint8_t v); +void ALIVE_CHECKER_setIsAlive(ALIVE_CHECKER* me, bool v); +void ALIVE_CHECKER_ISALIVE(ALIVE_CHECKER* me); // Use this one when you receive CAN message + +#endif diff --git a/UML/alive.uxf b/UML/alive.uxf new file mode 100644 index 0000000..0f31457 --- /dev/null +++ b/UML/alive.uxf @@ -0,0 +1,178 @@ + + + 14 + + UMLSpecialState + + 266 + 98 + 28 + 28 + + type=initial + + + + Relation + + 266 + 112 + 112 + 98 + + lt=-> +evACinit + 10.0;10.0;10.0;50.0 + + + UMLState + + 210 + 182 + 140 + 56 + + STAC_SETUP + + + + UMLNote + + 434 + 182 + 140 + 42 + + Send params + + + + Relation + + 266 + 224 + 126 + 98 + + lt=-> +evACborn + 10.0;10.0;10.0;50.0 + + + UMLState + + 210 + 294 + 140 + 56 + + STAC_BORN + + + + UMLState + + 168 + 406 + 224 + 84 + + STAC_WAIT +-- +/entry: isAlive = false + + + + Relation + + 266 + 336 + 140 + 98 + + lt=-> +evACready + 10.0;10.0;10.0;50.0 + + + UMLState + + 210 + 658 + 140 + 56 + + STAC_DEAD + + + + Relation + + 266 + 476 + 112 + 98 + + lt=-> +evACpoll + 10.0;10.0;10.0;50.0 + + + UMLSpecialState + + 252 + 546 + 56 + 56 + + type=decision + + + + Relation + + 266 + 588 + 84 + 98 + + lt=-> +m1=[else] + 10.0;10.0;10.0;50.0 + + + UMLNote + + 434 + 294 + 140 + 42 + + Reset / Init + + + + Relation + + 294 + 420 + 182 + 196 + + lt=-> +m1=[alive] + 10.0;110.0;110.0;110.0;110.0;10.0;70.0;10.0 + + + Relation + + 140 + 308 + 168 + 490 + + lt=-> +evACborn + 100.0;290.0;100.0;330.0;10.0;330.0;10.0;10.0;50.0;10.0 + +