@@ -20,7 +20,7 @@ set(BITMAP_RLE_ARGS ${BITMAP_ARGS} --rle)
|
||||
set(MASK_RLE_ARGS ${MASK_ARGS} --rle)
|
||||
|
||||
add_bitmaps_target(${BITMAP_TARGET_PREFIX}_bitmaps "${RADIO_SRC_DIR}/bitmaps/480x272/bmp_*.png" "5/6/5" "${BITMAP_ARGS}")
|
||||
add_png_target(${BITMAP_TARGET_PREFIX}_splash "${RADIO_SRC_DIR}/bitmaps/480x272/big_logo.png")
|
||||
add_png_target(${BITMAP_TARGET_PREFIX}_splash "${RADIO_SRC_DIR}/bitmaps/480x272/splash.png")
|
||||
|
||||
add_bitmaps_target(${BITMAP_TARGET_PREFIX}_calibration_bitmaps "${RADIO_SRC_DIR}/bitmaps/480x272/calibration/bmp_*.png" "5/6/5" "${BITMAP_ARGS}")
|
||||
add_bitmaps_target(${BITMAP_TARGET_PREFIX}_button_bitmaps "${RADIO_SRC_DIR}/bitmaps/480x272/button/alpha_*.png" "4/4/4/4" "${BITMAP_ARGS}")
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 48 KiB |
@@ -157,9 +157,6 @@ void menuModelCustomScripts(event_t event)
|
||||
case SCRIPT_SYNTAX_ERROR:
|
||||
lcdDrawText(30*FW+2, y, "(error)");
|
||||
break;
|
||||
case SCRIPT_KILLED:
|
||||
lcdDrawText(29*FW+2, y, "(killed)");
|
||||
break;
|
||||
default:
|
||||
lcdDrawNumber(34*FW, y, luaGetCpuUsed(scriptIndex), RIGHT);
|
||||
lcdDrawChar(34*FW, y, '%');
|
||||
|
||||
@@ -177,7 +177,6 @@ bool displayTelemetryScreen()
|
||||
return false; // requested lua telemetry screen not available
|
||||
case SCRIPT_SYNTAX_ERROR:
|
||||
case SCRIPT_PANIC:
|
||||
case SCRIPT_KILLED:
|
||||
luaError(lsScripts, state, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -150,9 +150,6 @@ void menuModelCustomScripts(event_t event)
|
||||
case SCRIPT_SYNTAX_ERROR:
|
||||
lcdDrawText(30*FW+2, y, "(error)");
|
||||
break;
|
||||
case SCRIPT_KILLED:
|
||||
lcdDrawText(29*FW+2, y, "(killed)");
|
||||
break;
|
||||
default:
|
||||
lcdDrawNumber(34*FW, y, luaGetCpuUsed(scriptIndex), RIGHT);
|
||||
lcdDrawChar(34*FW, y, '%');
|
||||
|
||||
@@ -179,7 +179,6 @@ bool displayTelemetryScreen()
|
||||
return false; // requested lua telemetry screen not available
|
||||
case SCRIPT_SYNTAX_ERROR:
|
||||
case SCRIPT_PANIC:
|
||||
case SCRIPT_KILLED:
|
||||
luaError(lsScripts, state, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -167,7 +167,6 @@ class ScriptEditWindow : public Page {
|
||||
};
|
||||
|
||||
constexpr char SCRIPT_STATUS_ERROR[] = "(error)";
|
||||
constexpr char SCRIPT_STATUS_KILLED[] = "(killed)";
|
||||
|
||||
class ScriptLineButton : public Button
|
||||
{
|
||||
@@ -204,10 +203,6 @@ class ScriptLineButton : public Button
|
||||
dc->drawSizedText(x, y, SCRIPT_STATUS_ERROR,
|
||||
sizeof(SCRIPT_STATUS_ERROR), textColor);
|
||||
break;
|
||||
case SCRIPT_KILLED:
|
||||
dc->drawSizedText(x, y, SCRIPT_STATUS_KILLED,
|
||||
sizeof(SCRIPT_STATUS_KILLED), textColor);
|
||||
break;
|
||||
default:
|
||||
dc->drawNumber(x, y, runtimeData->instructions, textColor, 0, nullptr, "%");
|
||||
break;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#if defined(SPLASH)
|
||||
|
||||
const uint8_t __bmp_splash[] {
|
||||
#include "big_logo.lbm"
|
||||
#include "splash.lbm"
|
||||
};
|
||||
|
||||
void drawSplash()
|
||||
|
||||
@@ -155,20 +155,23 @@ void StandaloneLuaWindow::runLua(event_t evt)
|
||||
// Set global LUA LCD buffer
|
||||
luaLcdBuffer = &lcdBuffer;
|
||||
|
||||
TRACE("evt = 0x%x", evt);
|
||||
|
||||
bool hasRun = luaTask(evt, RUN_STNDAL_SCRIPT, true);
|
||||
if (hasRun) {
|
||||
if (luaState != INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
|
||||
if (luaTask(evt, true)) {
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
TRACE("# StandaloneLuaWindow::invalidate()");
|
||||
TRACE("# StandaloneLuaWindow::invalidate()");
|
||||
#endif
|
||||
invalidate();
|
||||
} else {
|
||||
invalidate();
|
||||
} else {
|
||||
// The script was preempted, and the LCD should not be updated yet
|
||||
}
|
||||
}
|
||||
|
||||
if (luaState == INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
|
||||
// Script does not run anymore...
|
||||
TRACE("LUA standalone script exited: deleting window!");
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
||||
// Kill global LUA LCD buffer
|
||||
luaLcdBuffer = nullptr;
|
||||
}
|
||||
|
||||
@@ -125,9 +125,9 @@ void Widget::paint(BitmapBuffer * dc)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void Widget::onEvent(event_t event)
|
||||
{
|
||||
#if defined(HARDWARE_KEYS)
|
||||
TRACE("### event = 0x%x ###", event);
|
||||
if (!fullscreen) {
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
@@ -145,8 +145,8 @@ void Widget::onEvent(event_t event)
|
||||
killEvents(event);
|
||||
setFullscreen(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Widget::update()
|
||||
{
|
||||
|
||||
@@ -83,11 +83,12 @@ class Widget : public Button
|
||||
|
||||
// Window interface
|
||||
void checkEvents() override;
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY,
|
||||
coord_t slideX, coord_t slideY) override;
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override;
|
||||
#endif
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
|
||||
@@ -72,6 +72,18 @@ constexpr bool IS_VIRTUAL_KEY_EVENT(event_t event)
|
||||
{
|
||||
return (event & 0xF000) == _MSK_VIRTUAL_KEY;
|
||||
}
|
||||
|
||||
// Touch events for Lua widgets - assuming _MSK_KEY_* for PCBHORUS
|
||||
constexpr event_t EVT_TOUCH = EVT_VIRTUAL_KEY('t');
|
||||
constexpr event_t EVT_TOUCH_FIRST = EVT_TOUCH | _MSK_KEY_FIRST;
|
||||
constexpr event_t EVT_TOUCH_BREAK = EVT_TOUCH | _MSK_KEY_BREAK;
|
||||
constexpr event_t EVT_TOUCH_SLIDE = EVT_TOUCH | _MSK_KEY_LONG;
|
||||
constexpr event_t EVT_TOUCH_TAP = EVT_TOUCH | _MSK_KEY_REPT;
|
||||
|
||||
constexpr bool IS_TOUCH_EVENT(event_t event)
|
||||
{
|
||||
return (event & ~_MSK_KEY_FLAGS) == EVT_TOUCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
// normal order of events is: FIRST, LONG, REPEAT, REPEAT, ..., BREAK
|
||||
|
||||
@@ -47,7 +47,10 @@ static int8_t getTextVerticalOffset(LcdFlags flags)
|
||||
if (font_index >= sizeof(text_vertical_offset)) {
|
||||
return 0;
|
||||
}
|
||||
return text_vertical_offset[font_index];
|
||||
int vcenter = 0;
|
||||
if (flags & VCENTERED)
|
||||
vcenter = 0.5 * getFontHeight(flags & 0xFFFF);
|
||||
return text_vertical_offset[font_index] - vcenter;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
|
||||
@@ -1083,12 +1083,13 @@ Stops key state machine. See [Key Events](../key_events.md) for the detailed des
|
||||
*/
|
||||
static int luaKillEvents(lua_State * L)
|
||||
{
|
||||
uint8_t key = EVT_KEY_MASK(luaL_checkinteger(L, 1));
|
||||
event_t key = EVT_KEY_MASK(luaL_checkinteger(L, 1));
|
||||
// prevent killing maskable keys (only in telemetry scripts)
|
||||
// TODO add which tpye of script is running before p_call()
|
||||
// TODO add which type of script is running before lua_resume()
|
||||
if (IS_MASKABLE(key)) {
|
||||
killEvents(key);
|
||||
}
|
||||
luaEmptyEventBuffer();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1862,6 +1863,7 @@ const luaR_value_entry opentxConstants[] = {
|
||||
#endif
|
||||
#if defined(COLORLCD)
|
||||
{ "BOLD", FONT(BOLD) },
|
||||
{ "VCENTER", VCENTERED },
|
||||
#else
|
||||
{ "BOLD", BOLD },
|
||||
#endif
|
||||
@@ -2099,6 +2101,13 @@ const luaR_value_entry opentxConstants[] = {
|
||||
{ "EVT_ROT_RIGHT", EVT_ROTARY_RIGHT },
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
{ "EVT_TOUCH_FIRST", EVT_TOUCH_FIRST },
|
||||
{ "EVT_TOUCH_BREAK", EVT_TOUCH_BREAK },
|
||||
{ "EVT_TOUCH_SLIDE", EVT_TOUCH_SLIDE },
|
||||
{ "EVT_TOUCH_TAP", EVT_TOUCH_TAP },
|
||||
#endif
|
||||
|
||||
#if LCD_DEPTH > 1 && !defined(COLORLCD)
|
||||
{ "FILL_WHITE", FILL_WHITE },
|
||||
{ "GREY_DEFAULT", GREY_DEFAULT },
|
||||
|
||||
+554
-446
File diff suppressed because it is too large
Load Diff
+42
-21
@@ -47,15 +47,19 @@ extern Fifo<uint8_t, LUA_FIFO_SIZE> * luaRxFifo;
|
||||
#endif
|
||||
|
||||
extern lua_State * lsScripts;
|
||||
extern lua_State * lsWidgets;
|
||||
|
||||
extern bool luaLcdAllowed;
|
||||
|
||||
#if defined(COLORLCD)
|
||||
extern lua_State * lsWidgets;
|
||||
extern uint32_t luaExtraMemoryUsage;
|
||||
void luaInitThemesAndWidgets();
|
||||
#endif
|
||||
|
||||
void luaInit();
|
||||
void luaInitThemesAndWidgets();
|
||||
void luaEmptyEventBuffer();
|
||||
|
||||
#define LUA_INIT_THEMES_AND_WIDGETS() luaInitThemesAndWidgets()
|
||||
#define lua_registernumber(L, n, i) (lua_pushnumber(L, (i)), lua_setglobal(L, (n)))
|
||||
#define lua_registerint(L, n, i) (lua_pushinteger(L, (i)), lua_setglobal(L, (n)))
|
||||
#define lua_pushtablenil(L, k) (lua_pushstring(L, (k)), lua_pushnil(L), lua_settable(L, -3))
|
||||
@@ -78,12 +82,6 @@ void luaInitThemesAndWidgets();
|
||||
|
||||
#define lua_registerlib(L, name, tab) (luaL_newmetatable(L, name), luaL_setfuncs(L, tab, 0), lua_setglobal(L, name))
|
||||
|
||||
#define RUN_MIX_SCRIPT (1 << 0)
|
||||
#define RUN_FUNC_SCRIPT (1 << 1)
|
||||
#define RUN_TELEM_BG_SCRIPT (1 << 2)
|
||||
#define RUN_TELEM_FG_SCRIPT (1 << 3)
|
||||
#define RUN_STNDAL_SCRIPT (1 << 4)
|
||||
|
||||
enum luaScriptInputType {
|
||||
INPUT_TYPE_FIRST = 0,
|
||||
INPUT_TYPE_VALUE = INPUT_TYPE_FIRST,
|
||||
@@ -98,27 +96,36 @@ struct ScriptInput {
|
||||
int16_t max;
|
||||
int16_t def;
|
||||
};
|
||||
|
||||
struct ScriptOutput {
|
||||
const char *name;
|
||||
int16_t value;
|
||||
};
|
||||
|
||||
enum ScriptState {
|
||||
SCRIPT_OK,
|
||||
SCRIPT_NOFILE,
|
||||
SCRIPT_SYNTAX_ERROR,
|
||||
SCRIPT_PANIC,
|
||||
SCRIPT_KILLED
|
||||
SCRIPT_FINISHED
|
||||
};
|
||||
|
||||
enum ScriptReference {
|
||||
#if defined(LUA_MODEL_SCRIPTS)
|
||||
SCRIPT_MIX_FIRST,
|
||||
SCRIPT_MIX_LAST=SCRIPT_MIX_FIRST+MAX_SCRIPTS-1,
|
||||
#endif
|
||||
SCRIPT_FUNC_FIRST,
|
||||
SCRIPT_FUNC_LAST=SCRIPT_FUNC_FIRST+MAX_SPECIAL_FUNCTIONS-1, // model functions
|
||||
SCRIPT_GFUNC_FIRST,
|
||||
SCRIPT_GFUNC_LAST=SCRIPT_GFUNC_FIRST+MAX_SPECIAL_FUNCTIONS-1, // global functions
|
||||
#if defined(PCBTARANIS)
|
||||
SCRIPT_TELEMETRY_FIRST,
|
||||
SCRIPT_TELEMETRY_LAST=SCRIPT_TELEMETRY_FIRST+MAX_SCRIPTS, // telem0 and telem1 .. telem7
|
||||
SCRIPT_TELEMETRY_LAST=SCRIPT_TELEMETRY_FIRST+MAX_SCRIPTS, // telem0 and telem1 .. telem7
|
||||
#endif
|
||||
SCRIPT_STANDALONE // Standalone script
|
||||
};
|
||||
|
||||
struct ScriptInternalData {
|
||||
uint8_t reference;
|
||||
uint8_t state;
|
||||
@@ -126,41 +133,55 @@ struct ScriptInternalData {
|
||||
int background;
|
||||
uint8_t instructions;
|
||||
};
|
||||
|
||||
struct ScriptInputsOutputs {
|
||||
uint8_t inputsCount;
|
||||
ScriptInput inputs[MAX_SCRIPT_INPUTS];
|
||||
uint8_t outputsCount;
|
||||
ScriptOutput outputs[MAX_SCRIPT_OUTPUTS];
|
||||
};
|
||||
#define INTERPRETER_RUNNING_STANDALONE_SCRIPT 1
|
||||
#define INTERPRETER_RELOAD_PERMANENT_SCRIPTS 2
|
||||
#define INTERPRETER_PANIC 255
|
||||
|
||||
|
||||
enum InterpreterState {
|
||||
INTERPRETER_RELOAD_PERMANENT_SCRIPTS = 1,
|
||||
INTERPRETER_LOADING,
|
||||
INTERPRETER_START_RUNNING,
|
||||
INTERPRETER_RUNNING,
|
||||
INTERPRETER_PANIC = 255
|
||||
};
|
||||
|
||||
extern uint8_t luaState;
|
||||
extern uint8_t luaScriptsCount;
|
||||
extern bool luaLcdAllowed;
|
||||
extern ScriptInternalData standaloneScript;
|
||||
|
||||
extern ScriptInternalData scriptInternalData[MAX_SCRIPTS];
|
||||
extern ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS];
|
||||
|
||||
void luaClose(lua_State ** L);
|
||||
bool luaTask(event_t evt, uint8_t scriptType, bool allowLcdUsage);
|
||||
bool luaTask(event_t evt, bool allowLcdUsage);
|
||||
void checkLuaMemoryUsage();
|
||||
void luaExec(const char * filename);
|
||||
void luaDoGc(lua_State * L, bool full);
|
||||
void luaError(lua_State * L, uint8_t error, bool acknowledge=true);
|
||||
uint32_t luaGetMemUsed(lua_State * L);
|
||||
void luaGetValueAndPush(lua_State * L, int src);
|
||||
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
|
||||
uint8_t isTelemetryScriptAvailable(uint8_t index);
|
||||
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||
#define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||
|
||||
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
|
||||
#define LUA_LOAD_MODEL_SCRIPTS() luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||
#define LUA_LOAD_MODEL_SCRIPT(idx) luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||
|
||||
// Lua PROTECT/UNPROTECT
|
||||
#include <setjmp.h>
|
||||
|
||||
struct our_longjmp {
|
||||
struct our_longjmp *previous;
|
||||
jmp_buf b;
|
||||
volatile int status; /* error code */
|
||||
};
|
||||
|
||||
extern struct our_longjmp * global_lj;
|
||||
|
||||
#define PROTECT_LUA() { struct our_longjmp lj; \
|
||||
lj.previous = global_lj; /* chain new error handler */ \
|
||||
global_lj = &lj; \
|
||||
@@ -172,14 +193,16 @@ extern uint16_t maxLuaDuration;
|
||||
extern uint8_t instructionsPercent;
|
||||
|
||||
#if defined(KEYS_GPIO_REG_PAGE)
|
||||
#define IS_MASKABLE(key) ((key) != KEY_EXIT && (key) != KEY_ENTER && ((luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) || (key) != KEY_PAGE))
|
||||
#define IS_MASKABLE(key) ((key) != KEY_EXIT && (key) != KEY_ENTER && ((scriptInternalData[0].reference == SCRIPT_STANDALONE) || (key) != KEY_PAGE))
|
||||
#else
|
||||
#define IS_MASKABLE(key) ((key) != KEY_EXIT && (key) != KEY_ENTER)
|
||||
#endif
|
||||
|
||||
struct LuaField {
|
||||
uint16_t id;
|
||||
char desc[50];
|
||||
};
|
||||
|
||||
bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags=0);
|
||||
void luaLoadThemes();
|
||||
void luaRegisterLibraries(lua_State * L);
|
||||
@@ -207,8 +230,6 @@ struct LuaMemTracer {
|
||||
};
|
||||
|
||||
void * tracer_alloc(void * ud, void * ptr, size_t osize, size_t nsize);
|
||||
void luaHook(lua_State * L, lua_Debug *ar);
|
||||
|
||||
|
||||
#else // defined(LUA)
|
||||
|
||||
|
||||
+226
-3
@@ -31,6 +31,13 @@
|
||||
#define MANUAL_SCRIPTS_MAX_INSTRUCTIONS (20000/100)
|
||||
#define LUA_WARNING_INFO_LEN 64
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
#define EVT_TOUCH_TAP_TIME 25
|
||||
#define EVT_TOUCH_SWIPE_LOCK 4
|
||||
#define EVT_TOUCH_SWIPE_SPEED 35
|
||||
#define EVT_TOUCH_SWIPE_TIMEOUT 50
|
||||
#endif
|
||||
|
||||
constexpr int LUA_WIDGET_REFRESH = 1000 / 10; // 10 Hz
|
||||
|
||||
lua_State * lsWidgets = NULL;
|
||||
@@ -40,6 +47,57 @@ extern int custom_lua_atpanic(lua_State *L);
|
||||
#define LUA_WIDGET_FILENAME "/main.lua"
|
||||
#define LUA_FULLPATH_MAXLEN (LEN_FILE_PATH_MAX + LEN_SCRIPT_FILENAME + LEN_FILE_EXTENSION_MAX) // max length (example: /SCRIPTS/THEMES/mytheme.lua)
|
||||
|
||||
static void luaHook(lua_State * L, lua_Debug *ar)
|
||||
{
|
||||
if (ar->event == LUA_HOOKCOUNT) {
|
||||
instructionsPercent++;
|
||||
#if defined(DEBUG)
|
||||
// Disable Lua script instructions limit in DEBUG mode,
|
||||
// just report max value reached
|
||||
static uint16_t max = 0;
|
||||
if (instructionsPercent > 100) {
|
||||
if (max + 10 < instructionsPercent) {
|
||||
max = instructionsPercent;
|
||||
TRACE("LUA instructionsPercent %u%%", (uint32_t)max);
|
||||
}
|
||||
}
|
||||
else if (instructionsPercent < 10) {
|
||||
max = 0;
|
||||
}
|
||||
#else
|
||||
if (instructionsPercent > 100) {
|
||||
// From now on, as soon as a line is executed, error
|
||||
// keep erroring until you're script reaches the top
|
||||
lua_sethook(L, luaHook, LUA_MASKLINE, 0);
|
||||
luaL_error(L, "CPU limit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(LUA_ALLOCATOR_TRACER)
|
||||
else if (ar->event == LUA_HOOKLINE) {
|
||||
lua_getinfo(L, "nSl", ar);
|
||||
LuaMemTracer * tracer = GET_TRACER(L);
|
||||
if (tracer->alloc || tracer->free) {
|
||||
TRACE("LT: [+%u,-%u] %s:%d", tracer->alloc, tracer->free, tracer->script, tracer->lineno);
|
||||
}
|
||||
tracer->script = ar->source;
|
||||
tracer->lineno = ar->currentline;
|
||||
tracer->alloc = 0;
|
||||
tracer->free = 0;
|
||||
}
|
||||
#endif // #if defined(LUA_ALLOCATOR_TRACER)
|
||||
}
|
||||
|
||||
void luaSetInstructionsLimit(lua_State * L, int count)
|
||||
{
|
||||
instructionsPercent = 0;
|
||||
#if defined(LUA_ALLOCATOR_TRACER)
|
||||
lua_sethook(L, luaHook, LUA_MASKCOUNT|LUA_MASKLINE, count);
|
||||
#else
|
||||
lua_sethook(L, luaHook, LUA_MASKCOUNT, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
void exec(int function, int nresults=0)
|
||||
{
|
||||
if (lsWidgets == 0) return;
|
||||
@@ -190,6 +248,16 @@ class LuaWidget: public Widget
|
||||
const char * getErrorMessage() const override;
|
||||
void update() override;
|
||||
void background() override;
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchStart(coord_t x, coord_t y) override;
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override;
|
||||
#endif
|
||||
|
||||
// Calls LUA widget 'refresh' method
|
||||
void refresh(BitmapBuffer* dc) override;
|
||||
@@ -199,11 +267,36 @@ class LuaWidget: public Widget
|
||||
char * errorMessage;
|
||||
uint32_t lastRefresh = 0;
|
||||
bool refreshed = false;
|
||||
|
||||
static event_t event;
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
static coord_t touchX;
|
||||
static coord_t touchY;
|
||||
static coord_t startX;
|
||||
static coord_t startY;
|
||||
static coord_t slideX;
|
||||
static coord_t slideY;
|
||||
static tmr10ms_t lastTouchDown;
|
||||
static tmr10ms_t swipeTimeOut;
|
||||
#endif
|
||||
void checkEvents() override;
|
||||
void setErrorMessage(const char * funcName);
|
||||
};
|
||||
|
||||
event_t LuaWidget::event = 0;
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
coord_t LuaWidget::touchX = 0;
|
||||
coord_t LuaWidget::touchY = 0;
|
||||
coord_t LuaWidget::startX = 0;
|
||||
coord_t LuaWidget::startY = 0;
|
||||
coord_t LuaWidget::slideX = 0;
|
||||
coord_t LuaWidget::slideY = 0;
|
||||
tmr10ms_t LuaWidget::lastTouchDown = 0;
|
||||
tmr10ms_t LuaWidget::swipeTimeOut = 0;
|
||||
#endif
|
||||
|
||||
void l_pushtableint(const char * key, int value)
|
||||
{
|
||||
lua_pushstring(lsWidgets, key);
|
||||
@@ -211,6 +304,13 @@ void l_pushtableint(const char * key, int value)
|
||||
lua_settable(lsWidgets, -3);
|
||||
}
|
||||
|
||||
void l_pushtablebool(const char * key, bool value)
|
||||
{
|
||||
lua_pushstring(lsWidgets, key);
|
||||
lua_pushboolean(lsWidgets, value);
|
||||
lua_settable(lsWidgets, -3);
|
||||
}
|
||||
|
||||
class LuaWidgetFactory: public WidgetFactory
|
||||
{
|
||||
friend void luaLoadWidgetCallback();
|
||||
@@ -341,15 +441,66 @@ void LuaWidget::refresh(BitmapBuffer* dc)
|
||||
LuaWidgetFactory * factory = (LuaWidgetFactory *)this->factory;
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, factory->refreshFunction);
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef);
|
||||
|
||||
// Pass key event to fullscreen Lua widget
|
||||
if (fullscreen)
|
||||
lua_pushinteger(lsWidgets, event);
|
||||
else
|
||||
lua_pushnil(lsWidgets);
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
if (fullscreen && IS_TOUCH_EVENT(event)) {
|
||||
lua_newtable(lsWidgets);
|
||||
l_pushtableint("x", touchX);
|
||||
l_pushtableint("y", touchY);
|
||||
|
||||
if (LuaWidget::event == EVT_TOUCH_SLIDE) {
|
||||
l_pushtableint("startX", startX);
|
||||
l_pushtableint("startY", startY);
|
||||
l_pushtableint("slideX", slideX);
|
||||
l_pushtableint("slideY", slideY);
|
||||
|
||||
// Do we have a swipe? Only one at a time!
|
||||
if (get_tmr10ms() > swipeTimeOut) {
|
||||
coord_t absX = (slideX < 0) ? -slideX : slideX;
|
||||
coord_t absY = (slideY < 0) ? -slideY : slideY;
|
||||
bool swiped = false;
|
||||
|
||||
if (absX > EVT_TOUCH_SWIPE_LOCK * absY) {
|
||||
if ((swiped = (slideX > EVT_TOUCH_SWIPE_SPEED)))
|
||||
l_pushtablebool("swipeRight", true);
|
||||
else if ((swiped = (slideX < -EVT_TOUCH_SWIPE_SPEED)))
|
||||
l_pushtablebool("swipeLeft", true);
|
||||
}
|
||||
else if (absY > EVT_TOUCH_SWIPE_LOCK * absX) {
|
||||
if ((swiped = (slideY > EVT_TOUCH_SWIPE_SPEED)))
|
||||
l_pushtablebool("swipeDown", true);
|
||||
else if ((swiped = (slideY < -EVT_TOUCH_SWIPE_SPEED)))
|
||||
l_pushtablebool("swipeUp", true);
|
||||
}
|
||||
|
||||
if (swiped)
|
||||
swipeTimeOut = get_tmr10ms() + EVT_TOUCH_SWIPE_TIMEOUT;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
lua_pushnil(lsWidgets);
|
||||
|
||||
event = 0;
|
||||
|
||||
// Enable drawing into the current LCD buffer
|
||||
luaLcdBuffer = dc;
|
||||
|
||||
// This little hack is needed to not interfere with the LCD usage of preempted scripts
|
||||
bool lla = luaLcdAllowed;
|
||||
luaLcdAllowed = true;
|
||||
if (lua_pcall(lsWidgets, 1, 0, 0) != 0) {
|
||||
|
||||
if (lua_pcall(lsWidgets, 3, 0, 0) != 0) {
|
||||
setErrorMessage("refresh()");
|
||||
}
|
||||
// Remove LCD
|
||||
luaLcdAllowed = false;
|
||||
luaLcdAllowed = lla;
|
||||
luaLcdBuffer = nullptr;
|
||||
|
||||
// mark as refreshed
|
||||
@@ -360,7 +511,7 @@ void LuaWidget::background()
|
||||
{
|
||||
if (lsWidgets == 0 || errorMessage) return;
|
||||
|
||||
TRACE("LuaWidget::background()");
|
||||
// TRACE("LuaWidget::background()");
|
||||
luaSetInstructionsLimit(lsWidgets, WIDGET_SCRIPTS_MAX_INSTRUCTIONS);
|
||||
LuaWidgetFactory * factory = (LuaWidgetFactory *)this->factory;
|
||||
if (factory->backgroundFunction) {
|
||||
@@ -372,6 +523,78 @@ void LuaWidget::background()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void LuaWidget::onEvent(event_t event)
|
||||
{
|
||||
if (fullscreen && EVT_KEY_LONG(KEY_EXIT) != event)
|
||||
LuaWidget::event = event;
|
||||
else
|
||||
LuaWidget::event = 0;
|
||||
|
||||
Widget::onEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool LuaWidget::onTouchStart(coord_t x, coord_t y)
|
||||
{
|
||||
TRACE_WINDOWS("LuaWidget received touch start (%d) x=%d;y=%d", hasFocus(), x, y);
|
||||
|
||||
// Only one EVT_TOUCH_FIRST at a time, and also start timer for possible TAP
|
||||
if (fullscreen) {
|
||||
if (lastTouchDown == 0) {
|
||||
event = EVT_TOUCH_FIRST;
|
||||
touchX = x;
|
||||
touchY = y;
|
||||
lastTouchDown = get_tmr10ms();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return Widget::onTouchStart(x, y);
|
||||
}
|
||||
|
||||
bool LuaWidget::onTouchEnd(coord_t x, coord_t y)
|
||||
{
|
||||
TRACE_WINDOWS("LuaWidget received touch end (%d) x=%d;y=%d", hasFocus(), x, y);
|
||||
|
||||
if (fullscreen) {
|
||||
if (get_tmr10ms() - lastTouchDown <= EVT_TOUCH_TAP_TIME)
|
||||
event = EVT_TOUCH_TAP;
|
||||
else
|
||||
event = EVT_TOUCH_BREAK;
|
||||
|
||||
touchX = x;
|
||||
touchY = y;
|
||||
lastTouchDown = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return Widget::onTouchEnd(x, y);
|
||||
}
|
||||
|
||||
bool LuaWidget::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY)
|
||||
{
|
||||
TRACE_WINDOWS("LuaWidget touch slide");
|
||||
if (fullscreen) {
|
||||
event = EVT_TOUCH_SLIDE;
|
||||
touchX = x;
|
||||
touchY = y;
|
||||
LuaWidget::startX = startX;
|
||||
LuaWidget::startY = startY;
|
||||
LuaWidget::slideX = slideX;
|
||||
LuaWidget::slideY = slideY;
|
||||
lastTouchDown = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return Widget::onTouchSlide(x, y, startX, startY, slideX, slideY);
|
||||
}
|
||||
#endif
|
||||
|
||||
void luaLoadWidgetCallback()
|
||||
{
|
||||
TRACE("luaLoadWidgetCallback()");
|
||||
|
||||
+16
-17
@@ -356,7 +356,7 @@ void guiMain(event_t evt)
|
||||
DEBUG_TIMER_START(debugTimerLua);
|
||||
|
||||
// Run Lua scripts first that don't use LCD
|
||||
luaTask( 0, RUN_MIX_SCRIPT | RUN_FUNC_SCRIPT, false);
|
||||
luaTask( 0, false);
|
||||
|
||||
// This is run from StandaloneLuaWindow::checkEvents()
|
||||
// luaTask(evt, RUN_STNDAL_SCRIPT, true);
|
||||
@@ -382,29 +382,28 @@ void guiMain(event_t evt)
|
||||
}
|
||||
#elif defined(GUI)
|
||||
|
||||
void handleGui(event_t event) {
|
||||
// if Lua standalone, run it and don't clear the screen (Lua will do it)
|
||||
// else if Lua telemetry view, run it and don't clear the screen
|
||||
// else clear scren and show normal menus
|
||||
bool handleGui(event_t event) {
|
||||
bool refreshNeeded;
|
||||
#if defined(LUA)
|
||||
if (luaTask(event, RUN_STNDAL_SCRIPT, true)) {
|
||||
// standalone script is active
|
||||
refreshNeeded = luaTask(event, true);
|
||||
if (menuHandlers[menuLevel] == menuViewTelemetry && TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_SCRIPT) {
|
||||
menuHandlers[menuLevel](event);
|
||||
}
|
||||
else if (luaTask(event, RUN_TELEM_FG_SCRIPT, true)) {
|
||||
// the telemetry screen is active
|
||||
menuHandlers[menuLevel](event);
|
||||
}
|
||||
else
|
||||
else if (scriptInternalData[0].reference != SCRIPT_STANDALONE)
|
||||
#endif
|
||||
// No foreground Lua script is running - clear the screen show normal menu
|
||||
{
|
||||
lcdClear();
|
||||
menuHandlers[menuLevel](event);
|
||||
drawStatusLine();
|
||||
refreshNeeded = true;
|
||||
}
|
||||
return refreshNeeded;
|
||||
}
|
||||
|
||||
void guiMain(event_t evt)
|
||||
{
|
||||
bool refreshNeeded = menuEvent || warningText || (popupMenuItemsCount > 0);
|
||||
#if defined(LUA)
|
||||
// TODO better lua stopwatch
|
||||
uint32_t t0 = get_tmr10ms();
|
||||
@@ -416,7 +415,7 @@ void guiMain(event_t evt)
|
||||
}
|
||||
|
||||
// run Lua scripts that don't use LCD (to use CPU time while LCD DMA is running)
|
||||
luaTask(0, RUN_MIX_SCRIPT | RUN_FUNC_SCRIPT | RUN_TELEM_BG_SCRIPT, false);
|
||||
luaTask(0, false);
|
||||
|
||||
t0 = get_tmr10ms() - t0;
|
||||
if (t0 > maxLuaDuration) {
|
||||
@@ -440,10 +439,10 @@ void guiMain(event_t evt)
|
||||
}
|
||||
|
||||
if (isEventCaughtByPopup()) {
|
||||
handleGui(0);
|
||||
refreshNeeded |= handleGui(0);
|
||||
}
|
||||
else {
|
||||
handleGui(evt);
|
||||
refreshNeeded |= handleGui(evt);
|
||||
evt = 0;
|
||||
}
|
||||
|
||||
@@ -463,8 +462,8 @@ void guiMain(event_t evt)
|
||||
}
|
||||
}
|
||||
|
||||
lcdRefresh();
|
||||
|
||||
if (refreshNeeded) lcdRefresh();
|
||||
|
||||
if (mainRequestFlags & (1u << REQUEST_SCREENSHOT)) {
|
||||
writeScreenshot();
|
||||
mainRequestFlags &= ~(1u << REQUEST_SCREENSHOT);
|
||||
|
||||
@@ -654,32 +654,6 @@ void doSplash()
|
||||
#define doSplash()
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD)
|
||||
void checkSDVersion()
|
||||
{
|
||||
if (sdMounted()) {
|
||||
FIL versionFile;
|
||||
UINT read = 0;
|
||||
char version[sizeof(REQUIRED_SDCARD_VERSION)-1];
|
||||
char error[sizeof(TR_WRONG_SDCARDVERSION)+ sizeof(version)];
|
||||
|
||||
strAppend(strAppend(error, STR_WRONG_SDCARDVERSION, sizeof(TR_WRONG_SDCARDVERSION)), REQUIRED_SDCARD_VERSION, sizeof(REQUIRED_SDCARD_VERSION));
|
||||
FRESULT result = f_open(&versionFile, "/edgetx.sdcard.version", FA_OPEN_EXISTING | FA_READ);
|
||||
if (result == FR_OK) {
|
||||
if (f_read(&versionFile, &version, sizeof(version), &read) != FR_OK ||
|
||||
read != sizeof(version) ||
|
||||
strncmp(version, REQUIRED_SDCARD_VERSION, sizeof(version)) != 0) {
|
||||
TRACE("SD card version mismatch: %.*s, %s", sizeof(REQUIRED_SDCARD_VERSION)-1, version, REQUIRED_SDCARD_VERSION);
|
||||
ALERT(STR_SD_CARD, error, AU_ERROR);
|
||||
}
|
||||
f_close(&versionFile);
|
||||
}
|
||||
else {
|
||||
ALERT(STR_SD_CARD, error, AU_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void checkMultiLowPower()
|
||||
@@ -738,9 +712,6 @@ void checkAll()
|
||||
checkSwitches();
|
||||
checkFailsafe();
|
||||
|
||||
#if defined(SDCARD) && !defined(RADIOMASTER_RTF_RELEASE)
|
||||
checkSDVersion();
|
||||
#endif
|
||||
|
||||
#if defined(STM32)
|
||||
if (isVBatBridgeEnabled() && !g_eeGeneral.disableRtcWarning) {
|
||||
|
||||
Reference in New Issue
Block a user