#pragma once #include "valuemutex.h" #include "pubsub.h" #include "event.h" #include #ifdef __cplusplus extern "C" { #endif /* == Value composer == */ typedef struct ValueComposer ValueComposer; typedef void (*ValueComposerCallback)(void* ctx, void* state); typedef enum { UiLayerBelowNotify, UiLayerNotify, UiLayerAboveNotify } UiLayer; typedef struct { ValueComposerCallback cb; void* ctx; UiLayer layer; ValueComposer* composer; } ValueComposerHandle; LIST_DEF(list_composer_cb, ValueComposerHandle, M_POD_OPLIST); struct ValueComposer { ValueMutex value; list_composer_cb_t layers[3]; osMutexId_t mutex; Event request; }; void COPY_COMPOSE(void* ctx, void* state); bool init_composer(ValueComposer* composer, void* value); /* Free resources allocated by `init_composer`. This function doesn't free the memory occupied by `ValueComposer` itself. */ bool delete_composer(ValueComposer* composer); ValueComposerHandle* add_compose_layer(ValueComposer* composer, ValueComposerCallback cb, void* ctx, UiLayer layer); bool remove_compose_layer(ValueComposerHandle* handle); void request_compose(ValueComposerHandle* handle); /* Perform composition if requested. `start_cb` and `end_cb` will be called before and after all layer callbacks, respectively. Both `start_cb` and `end_cb` can be NULL. They can be used to set initial state (e.g. clear screen) and commit the final state. */ void perform_compose( ValueComposer* composer, ValueComposerCallback start_cb, ValueComposerCallback end_cb, void* ctx); /* Perform composition. This function should be called with value mutex acquired. This function is here for convenience, so that developers can write their own compose loops. See `perform_compose` function body for an example. */ void perform_compose_internal(ValueComposer* composer, void* state); // See [LED](LED-API) or [Display](Display-API) API for examples. /* == ValueManager == More complicated concept is ValueManager. It is like ValueMutex, but user can subscribe to value updates. First of all you can use value and pubsub part as showing above: aquire/release mutex, read value, subscribe/unsubscribe pubsub. There are two specific methods for ValueManager: write_managed, commit_managed */ typedef struct { ValueMutex value; PubSub pubsub; } ValueManager; bool init_managed(ValueManager* managed, void* value, size_t size); /* Free resources allocated by `init_managed`. This function doesn't free the memory occupied by `ValueManager` itself. */ bool delete_managed(ValueManager* managed); /* acquire value, changes it and send notify with current value. */ bool write_managed(ValueManager* managed, void* data, size_t len, uint32_t timeout); /* commit_managed works as `release_mutex` but send notify with current value. */ bool commit_managed(ValueManager* managed, void* value); #ifdef __cplusplus } #endif