diff --git a/radio/src/lua/api_colorlcd.cpp b/radio/src/lua/api_colorlcd.cpp index 5e602e66f..3bd0faf5a 100644 --- a/radio/src/lua/api_colorlcd.cpp +++ b/radio/src/lua/api_colorlcd.cpp @@ -588,6 +588,84 @@ static int luaGetBitmapSize(lua_State * L) return 2; } +/*luadoc +@function Bitmap.resize(bitmap, width, height) + +Return a resized bitmap object + +@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open() + +@param width (number) the new bitmap width + +@param height (number) the new bitmap height + +@notice Only available on Horus + +@status current Introduced in 2.8.0 +*/ +static int luaBitmapResize(lua_State * L) +{ + const BitmapBuffer * b = checkBitmap(L, 1); + unsigned int w = luaL_checkunsigned(L, 2); + unsigned int h = luaL_checkunsigned(L, 3); + + if (!b) { + lua_pushnil(L); + return 1; + } + + BitmapBuffer **n = (BitmapBuffer**)lua_newuserdata(L, sizeof(BitmapBuffer*)); + + if (luaExtraMemoryUsage > LUA_MEM_EXTRA_MAX) { + // already allocated more than max allowed, fail + TRACE("luaOpenBitmap: Error, using too much memory %u/%u", + luaExtraMemoryUsage, LUA_MEM_EXTRA_MAX); + *n = 0; + } else { + *n = new BitmapBuffer(BMP_ARGB4444, w, h); + (*n)->clear(); + (*n)->drawScaledBitmap(b, 0, 0, w, h); + } + + if (*n) { + uint32_t size = (*n)->getDataSize(); + luaExtraMemoryUsage += size; + TRACE("luaResizeBitmap: %p (%u)", *n, size); + } + + luaL_getmetatable(L, LUA_BITMAPHANDLE); + lua_setmetatable(L, -2); + + return 1; +} + +/*luadoc +@function Bitmap.toMask(bitmap) + +Return a 8bit bitmap mask that can be used with lcd.drawBitmapPattern() + +@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open() + +@retval a bitmap mask + +@notice Only available on Horus + +@status current Introduced in 2.8.0 +*/ +static int luaBitmapTo8bitMask(lua_State * L) +{ + const BitmapBuffer * b = checkBitmap(L, 1); + if (b) { + size_t size; + auto mask = b->to8bitMask(&size); + lua_pushlstring(L, (char*)mask, size); + } + else { + lua_pushlstring(L, "\x00\x00\x00\x00", 4); + } + return 1; +} + static int luaDestroyBitmap(lua_State * L) { BitmapBuffer * b = checkBitmap(L, 1); @@ -608,6 +686,8 @@ static int luaDestroyBitmap(lua_State * L) const luaL_Reg bitmapFuncs[] = { { "open", luaOpenBitmap }, { "getSize", luaGetBitmapSize }, + { "resize", luaBitmapResize }, + { "toMask", luaBitmapTo8bitMask }, { "__gc", luaDestroyBitmap }, { NULL, NULL } }; @@ -659,6 +739,79 @@ static int luaLcdDrawBitmap(lua_State *L) return 0; } + +/*luadoc +@function lcd.drawBitmapPattern(bitmap, x, y [, flags]) + +Displays a bitmap pattern at (x,y) + +@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open() + +@param x,y (positive numbers) starting coordinates + +@param flags (optional) please see [Lcd functions overview](../lcd-functions-less-than-greater-than-luadoc-begin-lcd/lcd_functions-overview.html) + +@notice Only available on Horus + +@status current Introduced in 2.8.0 +*/ +static int luaLcdDrawBitmapPattern(lua_State *L) +{ + if (!luaLcdAllowed || !luaLcdBuffer) + return 0; + + const char* m = luaL_checkstring(L, 1); + + if (m) { + auto x = luaL_checkunsigned(L, 2); + auto y = luaL_checkunsigned(L, 3); + auto flags = luaL_optunsigned(L, 4, 0); + flags = flagsRGB(flags); + luaLcdBuffer->drawBitmapPattern(x, y, reinterpret_cast(m), flags); + } + + return 0; +} + +/*luadoc +@function lcd.drawBitmapPatternPie(bitmap, x, y, startAngle, endAngle [, flags]) + +Displays a bitmap pattern pie at (x,y) + +@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open() + +@param x,y (positive numbers) starting coordinates + +@param startAngle Start angle + +@param endAngle End angle + +@param flags (optional) please see [Lcd functions overview](../lcd-functions-less-than-greater-than-luadoc-begin-lcd/lcd_functions-overview.html) + +@notice Only available on Horus + +@status current Introduced in 2.8.0 +*/ +static int luaLcdDrawBitmapPatternPie(lua_State *L) +{ + if (!luaLcdAllowed || !luaLcdBuffer) + return 0; + + const char* m = luaL_checkstring(L, 1); + + if (m) { + auto x = luaL_checkunsigned(L, 2); + auto y = luaL_checkunsigned(L, 3); + auto startAngle = luaL_checkinteger(L, 4); + auto endAngle = luaL_checkinteger(L, 5); + auto flags = luaL_optunsigned(L, 6, 0); + flags = flagsRGB(flags); + luaLcdBuffer->drawBitmapPatternPie(x, y, reinterpret_cast(m), flags, startAngle, endAngle); + } + + return 0; +} + /*luadoc @function lcd.drawRectangle(x, y, w, h [, flags [, t [, opacity]]]) @@ -734,6 +887,39 @@ static int luaLcdDrawFilledRectangle(lua_State *L) } +/*luadoc +@function lcd.invertRect(x, y, w, h [, flags]) + +Invert a rectangle zone from top left corner (x,y) of specified width and height + +@param x,y (positive numbers) top left corner position + +@param w (number) width in pixels + +@param h (number) height in pixels + +@param flags (optional) please see [Lcd functions overview](../lcd-functions-less-than-greater-than-luadoc-begin-lcd/lcd_functions-overview.html) + +@status current Introduced in 2.8.0 +*/ +static int luaLcdInvertRect(lua_State *L) +{ + if (!luaLcdAllowed || !luaLcdBuffer) + return 0; + + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int w = luaL_checkinteger(L, 3); + int h = luaL_checkinteger(L, 4); + + LcdFlags flags = luaL_optunsigned(L, 5, 0); + flags = flagsRGB(flags); + + luaLcdBuffer->invertRect(x, y, w, h, flags); + + return 0; +} + /*luadoc @function lcd.drawGauge(x, y, w, h, fill, maxfill [, flags]) @@ -1249,6 +1435,7 @@ const luaL_Reg lcdLib[] = { { "drawLine", luaLcdDrawLine }, { "drawRectangle", luaLcdDrawRectangle }, { "drawFilledRectangle", luaLcdDrawFilledRectangle }, + { "invertRect", luaLcdInvertRect }, { "drawText", luaLcdDrawText }, { "drawTextLines", luaLcdDrawTextLines }, { "sizeText", luaLcdSizeText }, @@ -1259,6 +1446,8 @@ const luaL_Reg lcdLib[] = { { "drawSource", luaLcdDrawSource }, { "drawGauge", luaLcdDrawGauge }, { "drawBitmap", luaLcdDrawBitmap }, + { "drawBitmapPattern", luaLcdDrawBitmapPattern }, + { "drawBitmapPatternPie", luaLcdDrawBitmapPatternPie }, { "setColor", luaLcdSetColor }, { "getColor", luaLcdGetColor }, { "RGB", luaRGB }, diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index a68c6c7de..c1d6c585a 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -2447,6 +2447,27 @@ static int luaSources(lua_State * L) return 3; } +/*luadoc +@function getOutputValue(outputIndex) + +@param outputIndex: integer identifying the output channel number 0 for CH1, up to MAX_OUTPUT_CHANNELS - 1. + +@retval value current output value (number). Zero is returned for: + * non-existing outputs + +@status current Introduced in 2.8.0 +*/ +static int luaGetOutputValue(lua_State * L) +{ + mixsrc_t idx = luaL_checkinteger(L, 1); + if (idx >= 0 && idx < MAX_OUTPUT_CHANNELS) { + lua_pushinteger(L, channelOutputs[idx]); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + const luaL_Reg opentxLib[] = { { "getTime", luaGetTime }, { "getDateTime", luaGetDateTime }, @@ -2459,6 +2480,7 @@ const luaL_Reg opentxLib[] = { { "getRotEncSpeed", luaGetRotEncSpeed }, { "getRotEncMode", luaGetRotEncMode }, { "getValue", luaGetValue }, + { "getOutputValue", luaGetOutputValue }, { "getRAS", luaGetRAS }, { "getTxGPS", luaGetTxGPS }, { "getFieldInfo", luaGetFieldInfo }, @@ -2581,6 +2603,10 @@ const luaR_value_entry opentxConstants[] = { { "SWITCH_COUNT", SWSRC_COUNT }, { "MAX_SENSORS", MAX_TELEMETRY_SENSORS }, + { "MAX_OUTPUT_CHANNELS", MAX_OUTPUT_CHANNELS }, + { "LIMIT_EXT_PERCENT", LIMIT_EXT_PERCENT }, + { "LIMIT_STD_PERCENT", LIMIT_STD_PERCENT }, + { "LS_FUNC_NONE", LS_FUNC_NONE }, { "LS_FUNC_VEQUAL", LS_FUNC_VEQUAL }, { "LS_FUNC_VALMOSTEQUAL", LS_FUNC_VALMOSTEQUAL }, @@ -2631,6 +2657,8 @@ const luaR_value_entry opentxConstants[] = { { "COLOR", ZoneOption::Color }, { "BOOL", ZoneOption::Bool }, { "STRING", ZoneOption::String }, + { "TIMER", ZoneOption::Timer }, + { "TEXT_SIZE", ZoneOption::TextSize }, { "MENU_HEADER_HEIGHT", COLOR2FLAGS(MENU_HEADER_HEIGHT) }, // Colors gui/colorlcd/colors.h diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp index cdbf236d4..00af53270 100644 --- a/radio/src/lua/api_model.cpp +++ b/radio/src/lua/api_model.cpp @@ -38,22 +38,28 @@ Get current Model information @retval table model information: * `name` (string) model name + * `extendedLimits` (boolean) extended limits enabled + * `jitterFilter` (number) model level ADC filter * `bitmap` (string) bitmap name (not present on X7) * `filename` (string) model filename -@status current Introduced in 2.0.6, changed in 2.2.0, filename added in 2.6.0 +@status current Introduced in 2.0.6, changed in 2.2.0, filename added in 2.6.0, extendedLimits, jitterFilter, and labels added in 2.8.0 */ static int luaModelGetInfo(lua_State *L) { lua_newtable(L); lua_pushtablenstring(L, "name", g_model.header.name); + lua_pushtableboolean(L, "extendedLimits", g_model.extendedLimits); + lua_pushtableinteger(L, "jitterFilter", g_model.jitterFilter); #if LCD_DEPTH > 1 lua_pushtablenstring(L, "bitmap", g_model.header.bitmap); #endif #if defined(STORAGE_MODELSLIST) + lua_pushtablenstring(L, "labels", g_model.header.labels); lua_pushtablenstring(L, "filename", g_eeGeneral.currModelFilename); #else + lua_pushtablenstring(L, "labels", ""); char fname[MODELIDX_STRLEN + sizeof(YAML_EXT)]; getModelNumberStr(g_eeGeneral.currModel, fname); strcat(fname, YAML_EXT); @@ -73,7 +79,7 @@ Set the current Model information @notice If a parameter is missing from the value, then that parameter remains unchanged. -@status current Introduced in 2.0.6, changed in TODO +@status current Introduced in 2.0.6, extendedLimits and jitterFilter added in 2.8.0 */ static int luaModelSetInfo(lua_State *L) { @@ -88,6 +94,14 @@ static int luaModelSetInfo(lua_State *L) memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name)); #endif } + else if (!strcmp(key, "extendedLimits")) { + g_model.extendedLimits = lua_toboolean(L, -1); + } + else if (!strcmp(key, "jitterFilter")) { + auto j = lua_tounsigned(L, -1); + if (j > OVERRIDE_ON) j = OVERRIDE_ON; + g_model.jitterFilter = j; + } #if LCD_DEPTH > 1 else if (!strcmp(key, "bitmap")) { const char * name = luaL_checkstring(L, -1); @@ -260,8 +274,9 @@ Get model timer parameters * `minuteBeep` (boolean) minute beep * `persistent` (number) persistent timer * `name` (string) timer name + * `showElapsed` (boolean) show elapsed -@status current Introduced in 2.0.0, name added in 2.3.6 +@status current Introduced in 2.0.0, name added in 2.3.6, showElapsed added in 2.8.0 */ static int luaModelGetTimer(lua_State *L) { @@ -276,6 +291,7 @@ static int luaModelGetTimer(lua_State *L) lua_pushtableboolean(L, "minuteBeep", timer.minuteBeep); lua_pushtableinteger(L, "persistent", timer.persistent); lua_pushtablenstring(L, "name", timer.name); + lua_pushtableboolean(L, "showElapsed", timer.showElapsed); } else { lua_pushnil(L); @@ -295,7 +311,7 @@ Set model timer parameters @notice If a parameter is missing from the value, then that parameter remains unchanged. -@status current Introduced in 2.0.0, name added in 2.3.6 +@status current Introduced in 2.0.0, name added in 2.3.6, showElapsed added in 2.8.0 */ static int luaModelSetTimer(lua_State *L) { @@ -325,10 +341,13 @@ static int luaModelSetTimer(lua_State *L) else if (!strcmp(key, "persistent")) { timer.persistent = luaL_checkinteger(L, -1); } - if (!strcmp(key, "name")) { + else if (!strcmp(key, "name")) { const char * name = luaL_checkstring(L, -1); strncpy(timer.name, name, sizeof(timer.name)); } + else if (!strcmp(key, "showElapsed")) { + timer.showElapsed = lua_toboolean(L, -1); + } } storageDirty(EE_MODEL); } @@ -1616,6 +1635,87 @@ static int luaModelResetSensor(lua_State *L) return 1; } +#if defined(HELI) +/*luadoc +@function model.getSwashRing() + +Get heli swash parameters + +@retval table with heli swash parameters: +* `type` (number) 0=---, 1=120, 2=120X, 3=140, 4=90 +* `value` (number) swash ring value (normally 0) +* 'collectiveSource' (number) source index +* 'aileronSource' (number) source index +* 'elevatorSource' (number) source index +* 'collectiveWeight'(value) -100 to 100 +* 'aileronWeight' (value) -100 to 100 +* 'elevatorWeight' (value) -100 to 100 + + @status current Introduced in 2.8.0 +*/ +static int luaModelGetSwashRing(lua_State *L) +{ + lua_newtable(L); + lua_pushtableinteger(L, "type", g_model.swashR.type); + lua_pushtableinteger(L, "value", g_model.swashR.value); + lua_pushtableinteger(L, "collectiveSource", g_model.swashR.collectiveSource); + lua_pushtableinteger(L, "aileronSource", g_model.swashR.aileronSource); + lua_pushtableinteger(L, "elevatorSource", g_model.swashR.elevatorSource); + lua_pushtableinteger(L, "collectiveWeight", g_model.swashR.collectiveWeight); + lua_pushtableinteger(L, "aileronWeight", g_model.swashR.aileronWeight); + lua_pushtableinteger(L, "elevatorWeight", g_model.swashR.elevatorWeight); + + return 1; +} + +/*luadoc +@function model.setSwashRing(params) + +Set heli swash parameters + +@param value (table) swash ring parameters, see model.getSwashRing() for table format + +@notice If a parameter is missing, then that parameter remains unchanged. + +@status current Introduced in 2.8.0 +*/ +static int luaModelSetSwashRing(lua_State *L) +{ + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TSTRING); // key is string + const char * key = luaL_checkstring(L, -2); + if (!strcmp(key, "type")) { + g_model.swashR.type = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "value")) { + g_model.swashR.value = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "collectiveSource")) { + g_model.swashR.collectiveSource = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "aileronSource")) { + g_model.swashR.aileronSource = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "elevatorSource")) { + g_model.swashR.elevatorSource = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "collectiveWeight")) { + g_model.swashR.collectiveWeight = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "aileronWeight")) { + g_model.swashR.aileronWeight = luaL_checkinteger(L, -1); + } + else if (!strcmp(key, "elevatorWeight")) { + g_model.swashR.elevatorWeight = luaL_checkinteger(L, -1); + } + } + + storageDirty(EE_MODEL); + return 0; +} +#endif // HELI + const luaL_Reg modelLib[] = { { "getInfo", luaModelGetInfo }, { "setInfo", luaModelSetInfo }, @@ -1652,5 +1752,9 @@ const luaL_Reg modelLib[] = { #endif { "getSensor", luaModelGetSensor }, { "resetSensor", luaModelResetSensor }, - { NULL, NULL } /* sentinel */ +#if defined(HELI) + { "getSwashRing", luaModelGetSwashRing }, + { "setSwashRing", luaModelSetSwashRing }, +#endif + { nullptr, nullptr } /* sentinel */ };