/*
* EEZ Modular Firmware
* Copyright (C) 2015-present, Envox d.o.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#pragma once
#include
#include
namespace eez {
namespace gui {
static const uint32_t HEADER_TAG = 0x7A65657E;
static const uint8_t PROJECT_VERSION_V2 = 2;
static const uint8_t PROJECT_VERSION_V3 = 3;
static const uint8_t ASSETS_TYPE_FIRMWARE = 1;
static const uint8_t ASSETS_TYPE_FIRMWARE_MODULE = 2;
static const uint8_t ASSETS_TYPE_RESOURCE = 3;
static const uint8_t ASSETS_TYPE_APPLET = 4;
static const uint8_t ASSETS_TYPE_DASHBOARD = 5;
struct Header {
uint32_t tag; // HEADER_TAG
uint8_t projectMajorVersion;
uint8_t projectMinorVersion;
uint8_t assetsType;
uint8_t reserved;
uint32_t decompressedSize;
};
extern bool g_isMainAssetsLoaded;
extern Assets *g_mainAssets;
extern Assets *g_externalAssets;
////////////////////////////////////////////////////////////////////////////////
/* This template is used (on 64-bit systems) to pack asset pointers into 32-bit values.
* All pointers are relative to MEMORY_BEGIN.
* This way, the assets created by Studio can be used without having to fix all
* the sizes - Studio creates 32-bit pointers that are relative to the
* beginning of the assets, which the firmware rewrites to global pointers
* during initialization. On a 32-bit system this works just fine, but for a
* 64-bit system the pointers have different sizes and this breaks. By
* inserting a 'middleman' structure that stores the pointers as a 32-bit
* offset to MEMORY_BEGIN, we can keep the pointer sizes and initialization
* code the same.
*/
template
struct AssetsPtrImpl {
/* Conversion to a T pointer */
operator T*() { return ptr(); }
operator const T*() const { return ptr(); }
/* Dereferencing operators */
T* operator->() { return ptr(); }
const T* operator->() const { return ptr(); }
void operator=(T* ptr) {
if (ptr != nullptr) {
offset = (uint8_t *)ptr - MEMORY_BEGIN;
} else {
offset = 0;
}
}
uint32_t offset = 0;
private:
T* ptr() {
return offset ? (T *)(MEMORY_BEGIN + offset) : nullptr;
}
const T* ptr() const {
return offset ? (const T *)(MEMORY_BEGIN + offset) : nullptr;
}
};
/* This struct chooses the type used for AssetsPtr - by default it uses an AssetsPtrImpl<> */
template
struct AssetsPtrChooser
{
using type = AssetsPtrImpl;
};
/* On 32-bit systems, we can just use raw pointers */
template
struct AssetsPtrChooser
{
using type = T*;
};
/* Utility typedef that delegates to AssetsPtrChooser */
template
using AssetsPtr = typename AssetsPtrChooser::type;
////////////////////////////////////////////////////////////////////////////////
template
struct ListOfAssetsPtr {
/* Array access */
T* operator[](uint32_t i) { return item(i); }
const T* operator[](uint32_t i) const { return item(i); }
uint32_t count = 0;
AssetsPtr> items;
private:
T* item(int i) {
return static_cast(static_cast *>(items)[i]);
}
const T* item(int i) const {
return static_cast(static_cast *>(items)[i]);
}
};
template
struct ListOfFundamentalType {
/* Array access */
T& operator[](uint32_t i) { return ptr()[i]; }
const T& operator[](uint32_t i) const { return ptr()[i]; }
uint32_t count;
AssetsPtr items;
private:
T *ptr() {
return static_cast(items);
}
};
////////////////////////////////////////////////////////////////////////////////
struct Settings {
uint16_t displayWidth;
uint16_t displayHeight;
};
////////////////////////////////////////////////////////////////////////////////
#define WIDGET_FLAG_PIN_TO_LEFT (1 << 0)
#define WIDGET_FLAG_PIN_TO_RIGHT (1 << 1)
#define WIDGET_FLAG_PIN_TO_TOP (1 << 2)
#define WIDGET_FLAG_PIN_TO_BOTTOM (1 << 3)
#define WIDGET_FLAG_FIX_WIDTH (1 << 4)
#define WIDGET_FLAG_FIX_HEIGHT (1 << 5)
#define WIDGET_TIMELINE_PROPERTY_X (1 << 0)
#define WIDGET_TIMELINE_PROPERTY_Y (1 << 1)
#define WIDGET_TIMELINE_PROPERTY_WIDTH (1 << 2)
#define WIDGET_TIMELINE_PROPERTY_HEIGHT (1 << 3)
#define WIDGET_TIMELINE_PROPERTY_OPACITY (1 << 4)
#define EASING_FUNC_LINEAR 0
#define EASING_FUNC_IN_QUAD 1
#define EASING_FUNC_OUT_QUAD 2
#define EASING_FUNC_IN_OUT_QUAD 3
#define EASING_FUNC_IN_CUBIC 4
#define EASING_FUNC_OUT_CUBIC 5
#define EASING_FUNC_IN_OUT_CUBIC 6
#define EASING_FUNC_IN__QUART 7
#define EASING_FUNC_OUT_QUART 8
#define EASING_FUNC_IN_OUT_QUART 9
#define EASING_FUNC_IN_QUINT 10
#define EASING_FUNC_OUT_QUINT 11
#define EASING_FUNC_IN_OUT_QUINT 12
#define EASING_FUNC_IN_SINE 13
#define EASING_FUNC_OUT_SINE 14
#define EASING_FUNC_IN_OUT_SINE 15
#define EASING_FUNC_IN_EXPO 16
#define EASING_FUNC_OUT_EXPO 17
#define EASING_FUNC_IN_OUT_EXPO 18
#define EASING_FUNC_IN_CIRC 19
#define EASING_FUNC_OUT_CIRC 20
#define EASING_FUNC_IN_OUT_CIRC 21
#define EASING_FUNC_IN_BACK 22
#define EASING_FUNC_OUT_BACK 23
#define EASING_FUNC_IN_OUT_BACK 24
#define EASING_FUNC_IN_ELASTIC 25
#define EASING_FUNC_OUT_ELASTIC 26
#define EASING_FUNC_IN_OUT_ELASTIC 27
#define EASING_FUNC_IN_BOUNCE 28
#define EASING_FUNC_OUT_BOUNCE 29
#define EASING_FUNC_IN_OUT_BOUNCE 30
struct TimelineKeyframe {
float start;
float end;
uint32_t enabledProperties;
int16_t x;
int16_t y;
int16_t width;
int16_t height;
float opacity;
uint8_t xEasingFunc;
uint8_t yEasingFunc;
uint8_t widthEasingFunc;
uint8_t heightEasingFunc;
uint8_t opacityEasingFunc;
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
};
struct Widget {
uint16_t type;
int16_t data;
int16_t visible;
int16_t action;
int16_t x;
int16_t y;
int16_t width;
int16_t height;
int16_t style;
uint16_t flags;
ListOfAssetsPtr timeline;
};
#define SHADOW_FLAG (1 << 0)
#define CLOSE_PAGE_IF_TOUCHED_OUTSIDE_FLAG (1 << 1)
#define PAGE_IS_USED_AS_CUSTOM_WIDGET (1 << 2)
#define PAGE_CONTAINER (1 << 3)
#define PAGE_SCALE_TO_FIT (1 << 4)
struct PageAsset : public Widget {
ListOfAssetsPtr widgets;
uint16_t flags;
int16_t overlay;
};
////////////////////////////////////////////////////////////////////////////////
#define STYLE_FLAGS_HORZ_ALIGN_MASK 0x7
#define STYLE_FLAGS_HORZ_ALIGN_LEFT 0
#define STYLE_FLAGS_HORZ_ALIGN_RIGHT 1
#define STYLE_FLAGS_HORZ_ALIGN_CENTER 2
#define STYLE_FLAGS_VERT_ALIGN_MASK (0x7 << 3)
#define STYLE_FLAGS_VERT_ALIGN_TOP (0 << 3)
#define STYLE_FLAGS_VERT_ALIGN_BOTTOM (1 << 3)
#define STYLE_FLAGS_VERT_ALIGN_CENTER (2 << 3)
#define STYLE_FLAGS_BLINK (1 << 6)
struct Style {
uint16_t flags; // STYLE_FLAGS_...
uint16_t backgroundColor;
uint16_t color;
uint16_t activeBackgroundColor;
uint16_t activeColor;
uint16_t focusBackgroundColor;
uint16_t focusColor;
uint8_t borderSizeTop;
uint8_t borderSizeRight;
uint8_t borderSizeBottom;
uint8_t borderSizeLeft;
uint16_t borderColor;
uint8_t borderRadiusTLX;
uint8_t borderRadiusTLY;
uint8_t borderRadiusTRX;
uint8_t borderRadiusTRY;
uint8_t borderRadiusBLX;
uint8_t borderRadiusBLY;
uint8_t borderRadiusBRX;
uint8_t borderRadiusBRY;
uint8_t font;
uint8_t opacity; // 0 - 255
uint8_t paddingTop;
uint8_t paddingRight;
uint8_t paddingBottom;
uint8_t paddingLeft;
int16_t backgroundImage;
};
////////////////////////////////////////////////////////////////////////////////
struct GlyphData {
int8_t dx; // DWIDTH (-128 indicated empty glyph)
uint8_t width; // BBX width
uint8_t height; // BBX height
int8_t x; // BBX xoffset
int8_t y; // BBX yoffset
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
uint8_t pixels[1];
};
struct GlyphsGroup {
uint32_t encoding;
uint32_t glyphIndex;
uint32_t length;
};
struct FontData {
uint8_t ascent;
uint8_t descent;
uint8_t reserved1;
uint8_t reserved2;
uint32_t encodingStart;
uint32_t encodingEnd;
ListOfAssetsPtr groups;
ListOfAssetsPtr glyphs;
};
////////////////////////////////////////////////////////////////////////////////
struct Bitmap {
int16_t w;
int16_t h;
int16_t bpp;
int16_t reserved;
const uint8_t pixels[1];
};
////////////////////////////////////////////////////////////////////////////////
struct Theme {
AssetsPtr name;
ListOfFundamentalType colors;
};
struct Colors {
ListOfAssetsPtr themes;
ListOfFundamentalType colors;
};
////////////////////////////////////////////////////////////////////////////////
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_MASK = 0x0007 << 13;
static const uint16_t EXPR_EVAL_INSTRUCTION_PARAM_MASK = 0xFFFF >> 3;
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_CONSTANT = (0 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_INPUT = (1 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_LOCAL_VAR = (2 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_GLOBAL_VAR = (3 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_OUTPUT = (4 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_ARRAY_ELEMENT = (5 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_OPERATION = (6 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_END = (7 << 13);
struct Property {
uint8_t evalInstructions[1];
};
struct Connection {
uint16_t targetComponentIndex;
uint16_t targetInputIndex;
};
struct ComponentOutput {
ListOfAssetsPtr connections;
uint32_t isSeqOut;
};
static const uint16_t BREAKPOINT_ENABLED = 1;
static const uint16_t BREAKPOINT_DISABLED = 2;
struct Component {
uint16_t type;
uint16_t breakpoint;
// These are indexes to Flow::componentInputs.
// We use this to check if component is ready to run (i.e. all mandatory inputs have a value).
ListOfFundamentalType inputs;
ListOfAssetsPtr properties;
ListOfAssetsPtr outputs;
int16_t errorCatchOutput;
uint16_t reserved;
};
struct WidgetDataItem {
int16_t componentIndex;
int16_t propertyValueIndex;
};
struct WidgetActionItem {
int16_t componentIndex;
int16_t componentOutputIndex;
};
#define COMPONENT_INPUT_FLAG_IS_SEQ_INPUT (1 << 0)
#define COMPONENT_INPUT_FLAG_IS_OPTIONAL (1 << 1)
typedef uint8_t ComponentInput;
struct Flow {
ListOfAssetsPtr components;
ListOfAssetsPtr localVariables;
// List of all component inputs of all components in this flow
// When flow state is created we reserve this many Value's in memory
// to keep the latest value of component input.
ListOfFundamentalType componentInputs;
ListOfAssetsPtr widgetDataItems;
ListOfAssetsPtr widgetActions;
};
struct FlowDefinition {
ListOfAssetsPtr flows;
ListOfAssetsPtr constants;
ListOfAssetsPtr globalVariables;
};
struct Language {
AssetsPtr languageID;
ListOfAssetsPtr translations;
};
////////////////////////////////////////////////////////////////////////////////
struct Assets {
uint8_t projectMajorVersion;
uint8_t projectMinorVersion;
uint8_t assetsType;
uint8_t external;
AssetsPtr settings;
ListOfAssetsPtr pages;
ListOfAssetsPtr