feat(lua): Add several Lua API funcs and constants (#2279)
* LUA: Add Bitmap.toMask and lcd.drawBitmapPattern functions * LUA: Add lcd.invertRect function * LUA: Add Bitmap.resize function * LUA: Add getOutputValue function * LUA: Add timer showElapsed configuration * LUA: Add model extendedLimits configuration * LUA: Add some global constants * Add model jitterFilter configuration * Add model.getSwashRing and setSwashRing functions
This commit is contained in:
@@ -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<const uint8_t*>(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<const uint8_t*>(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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
+110
-6
@@ -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 */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user