esp32 firmware for a toaster reflow oven WIP!!!!!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
reflower/main/liquid/liquid.c

115 lines
3.6 KiB

#include "liquid.h"
#include "rom/queue.h"
#include "scenes.h"
#include <malloc.h>
#include <assert.h>
#include <esp_log.h>
static const char *TAG = "Liquid";
struct RunningScene {
struct Scene *scene;
SLIST_ENTRY(RunningScene) next;
} cmd_item_t;
struct Liquid {
SLIST_HEAD(, RunningScene) stack; // stack with the topmost scene as the first element / head
};
static struct SceneEvent Default_onChildReturn(struct Scene *scene, uint32_t tag, uint32_t status, void *data) {
if (data) free(data);
return SceneEvent_Repaint();
}
static void addChild(struct Liquid *container, struct Scene *child) {
struct RunningScene *elm = calloc(1, sizeof(struct RunningScene));
if (!child->onChildReturn) child->onChildReturn = Default_onChildReturn;
assert(child->paint != NULL);
elm->scene = child;
SLIST_INSERT_HEAD(&container->stack, elm, next);
}
struct Liquid *Liquid_start() {
struct Liquid *container = calloc(1, sizeof(struct Liquid));
addChild(container, NewScene_Root());
Liquid_paint(container);
return container;
}
static struct SceneEvent handleSceneEvent(struct Liquid *container, struct SceneEvent event) {
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
switch (event.kind) {
case SceneEventKind_Close:
assert(SLIST_NEXT(topmost, next) != NULL);
SLIST_REMOVE_HEAD(&container->stack, next);
uint32_t tag = topmost->scene->tag;
if (topmost->scene->options) {
free(topmost->scene->options);
}
free(topmost->scene);
free(topmost);
topmost = SLIST_FIRST(&container->stack);
// this is always set.
return topmost->scene->onChildReturn(topmost->scene, tag, event.close.status, event.close.data);
case SceneEventKind_OpenChild:;
if (!event.open.scene) {
ESP_LOGE(TAG, "Attempt to open NULL scene!");
return SceneEvent_None();
}
struct Scene *newScene = event.open.scene;
newScene->tag = event.open.tag;
addChild(container, newScene);
return SceneEvent_Repaint();
case SceneEventKind_RequestRepaint:
case SceneEventKind_None:
default:
// this shouldn't get here
return event;
}
}
bool processReturnValue(struct Liquid *container, struct SceneEvent result) {
while (result.kind != SceneEventKind_None) {
if (result.kind == SceneEventKind_RequestRepaint) {
return 1; // repaint
}
result = handleSceneEvent(container, result);
}
return 0;
}
bool Liquid_handleInput(struct Liquid *container, struct InputEvent event) {
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
assert(topmost != NULL);
assert(topmost->scene != NULL);
if (topmost->scene->onInput) {
struct SceneEvent result = topmost->scene->onInput(topmost->scene, event);
return processReturnValue(container, result);
} else {
return false;
}
}
bool Liquid_handleTick(struct Liquid *container) {
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
assert(topmost != NULL);
assert(topmost->scene != NULL);
if (topmost->scene->onTick) {
struct SceneEvent result = topmost->scene->onTick(topmost->scene);
return processReturnValue(container, result);
} else {
return false;
}
}
void Liquid_paint(struct Liquid *container) {
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
assert(topmost != NULL);
topmost->scene->paint(topmost->scene);
}