mirror of
https://github.com/EdgeTX/edgetx.git
synced 2025-07-19 14:25:09 +03:00
Schwabe/lua set curve (#4955)
* Implement setCurve for lua * Bug fixes after actual testing of API * Fix documentation * Even more error checking * Add example code how to use this function * Silence gcc warnings * Drop points and start array index at 1 and note about wrong index in getCurve * Add standard example * Fixes * Don’t use an invalid number in example * fix missing 0
This commit is contained in:
parent
1cb0156cd0
commit
cd23fedb56
3 changed files with 194 additions and 2 deletions
|
@ -168,7 +168,7 @@ enum CurveType {
|
||||||
#define LEN_INPUT_NAME 3
|
#define LEN_INPUT_NAME 3
|
||||||
#define LEN_CURVE_NAME 3
|
#define LEN_CURVE_NAME 3
|
||||||
#define LEN_FUNCTION_NAME 6
|
#define LEN_FUNCTION_NAME 6
|
||||||
#define MAX_CURVES 16
|
#define MAX_CURVES 16 // TODO next EEPROM check if can be changed to 32 to have all ARM the same
|
||||||
#define MAX_CURVE_POINTS 512
|
#define MAX_CURVE_POINTS 512
|
||||||
#elif defined(PCBTARANIS)
|
#elif defined(PCBTARANIS)
|
||||||
#define LEN_MODEL_NAME 12
|
#define LEN_MODEL_NAME 12
|
||||||
|
|
|
@ -367,7 +367,7 @@ PACK(struct FlightModeData {
|
||||||
PACK(struct CurveData {
|
PACK(struct CurveData {
|
||||||
uint8_t type:1;
|
uint8_t type:1;
|
||||||
uint8_t smooth:1;
|
uint8_t smooth:1;
|
||||||
int8_t points:6; // TODO conversion
|
int8_t points:6; // TODO conversion (?!) (describes number of points - 5)
|
||||||
NOBACKUP(char name[LEN_CURVE_NAME]);
|
NOBACKUP(char name[LEN_CURVE_NAME]);
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -805,6 +805,9 @@ Get Curve parameters
|
||||||
* `key` is point number (zero based)
|
* `key` is point number (zero based)
|
||||||
* `value` is x value
|
* `value` is x value
|
||||||
|
|
||||||
|
Note that functions returns the tables starting with index 0 contrary to LUA's
|
||||||
|
usual index starting with 1
|
||||||
|
|
||||||
@status current Introduced in 2.0.12
|
@status current Introduced in 2.0.12
|
||||||
*/
|
*/
|
||||||
static int luaModelGetCurve(lua_State *L)
|
static int luaModelGetCurve(lua_State *L)
|
||||||
|
@ -849,6 +852,194 @@ static int luaModelGetCurve(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function model.setCurve(curve, params)
|
||||||
|
|
||||||
|
Set Curve parameters
|
||||||
|
|
||||||
|
@param curve (unsigned number) curve number (use 0 for Curve1)
|
||||||
|
|
||||||
|
@param params see model.getCurve return format for table format. setCurve uses standard
|
||||||
|
lua array indexing and array start at index 1
|
||||||
|
|
||||||
|
The first and last x value must 0 and 100 and x values must be monotonically increasing
|
||||||
|
|
||||||
|
@retval 0 - Everything okay
|
||||||
|
1 - Wrong number of points
|
||||||
|
2 - Invalid Curve number
|
||||||
|
3 - Cuve does not fit anymore
|
||||||
|
4 - point of out of index
|
||||||
|
5 - x value not monotonically increasing
|
||||||
|
6 - y value not in range [-100;100]
|
||||||
|
7 - extra values for y are set
|
||||||
|
8 - extra values for x are set
|
||||||
|
|
||||||
|
@status current Introduced in 2.2.1
|
||||||
|
|
||||||
|
Example setting a 4-point custom curve:
|
||||||
|
```lua
|
||||||
|
params = {}
|
||||||
|
params["x"] = {0, 34, 77, 100}
|
||||||
|
params["y"] = {-70, 20, -89, -100}
|
||||||
|
params["smooth"] = 1
|
||||||
|
params["type"] = 1
|
||||||
|
val = model.setCurve(2, params)
|
||||||
|
```
|
||||||
|
setting a 6-point standard smoothed curve
|
||||||
|
```lua
|
||||||
|
val = model.setCurve(3, {smooth=1, y={-100, -50, 0, 50, 100, 80}})
|
||||||
|
```
|
||||||
|
|
||||||
|
*/
|
||||||
|
static int luaModelSetCurve(lua_State *L)
|
||||||
|
{
|
||||||
|
unsigned int curveIdx = luaL_checkunsigned(L, 1);
|
||||||
|
|
||||||
|
if (curveIdx >= MAX_CURVES) {
|
||||||
|
lua_pushinteger(L, 2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int8_t xPoints[MAX_POINTS_PER_CURVE];
|
||||||
|
int8_t yPoints[MAX_POINTS_PER_CURVE];
|
||||||
|
|
||||||
|
// Init to invalid values
|
||||||
|
memset(xPoints, -127, sizeof(xPoints));
|
||||||
|
memset(yPoints, -127, sizeof(yPoints));
|
||||||
|
|
||||||
|
|
||||||
|
CurveData &destCurveData = g_model.curves[curveIdx];
|
||||||
|
CurveData newCurveData;
|
||||||
|
memclear(&newCurveData, sizeof(CurveData));
|
||||||
|
|
||||||
|
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, "name")) {
|
||||||
|
const char *name = luaL_checkstring(L, -1);
|
||||||
|
str2zchar(newCurveData.name, name, sizeof(newCurveData.name));
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "type")) {
|
||||||
|
newCurveData.type = luaL_checkinteger(L, -1);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "smooth")) {
|
||||||
|
newCurveData.smooth = luaL_checkinteger(L, -1);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "x") || !strcmp(key, "y")) {
|
||||||
|
luaL_checktype(L, -1, LUA_TTABLE);
|
||||||
|
bool isX = !strcmp(key, "x");
|
||||||
|
|
||||||
|
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||||
|
int idx = luaL_checkinteger(L, -2)-1;
|
||||||
|
if (idx < 0 || idx > MAX_POINTS_PER_CURVE) {
|
||||||
|
lua_pushinteger(L, 4);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int8_t val = luaL_checkinteger(L, -1);
|
||||||
|
if (val < -100 || val > 100) {
|
||||||
|
lua_pushinteger(L, 6);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (isX)
|
||||||
|
xPoints[idx] = val;
|
||||||
|
else
|
||||||
|
yPoints[idx] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check how many points are set
|
||||||
|
uint8_t numPoints=0;
|
||||||
|
do {
|
||||||
|
numPoints++;
|
||||||
|
} while (yPoints[numPoints]!=-127 && numPoints < MAX_POINTS_PER_CURVE);
|
||||||
|
newCurveData.points = numPoints - 5;
|
||||||
|
|
||||||
|
if (numPoints < MIN_POINTS_PER_CURVE || numPoints > MAX_POINTS_PER_CURVE) {
|
||||||
|
lua_pushinteger(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newCurveData.type == CURVE_TYPE_CUSTOM) {
|
||||||
|
|
||||||
|
// The rest of the points are checked by the monotic condition
|
||||||
|
for (unsigned int i=numPoints; i < sizeof(xPoints);i++)
|
||||||
|
{
|
||||||
|
if (xPoints[i] != -127)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, 8);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check first and last point
|
||||||
|
if (xPoints[0] != 0 || xPoints[newCurveData.points + 4] != 100) {
|
||||||
|
lua_pushinteger(L, 5);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that x values are increasing
|
||||||
|
for (int i = 1; i < numPoints; i++) {
|
||||||
|
if (xPoints[i - 1] > xPoints[i]) {
|
||||||
|
lua_pushinteger(L, 5);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that ypoints have the right number of points set
|
||||||
|
for (int i=0; i < 5 + newCurveData.points;i++)
|
||||||
|
{
|
||||||
|
if (yPoints[i] == -127)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, 7);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate size of curve we replace
|
||||||
|
int oldCurveMemSize;
|
||||||
|
if (destCurveData.type == CURVE_TYPE_STANDARD) {
|
||||||
|
oldCurveMemSize = 5 + destCurveData.points;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oldCurveMemSize = 8 + 2 * destCurveData.points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate own size
|
||||||
|
int newCurveMemSize;
|
||||||
|
if (newCurveData.type == CURVE_TYPE_STANDARD)
|
||||||
|
newCurveMemSize = 5 + newCurveData.points;
|
||||||
|
else
|
||||||
|
newCurveMemSize = 8 + 2 * newCurveData.points;
|
||||||
|
|
||||||
|
int shift = newCurveMemSize - oldCurveMemSize;
|
||||||
|
|
||||||
|
// Also checks if new curve size would fit
|
||||||
|
if (!moveCurve(curveIdx, shift)) {
|
||||||
|
lua_pushinteger(L, 3);
|
||||||
|
TRACE("curve shift is %d", shift);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Curve fits into mem, fill new curve
|
||||||
|
destCurveData = newCurveData;
|
||||||
|
|
||||||
|
int8_t *point = curveAddress(curveIdx);
|
||||||
|
for (int i = 0; i < destCurveData.points + 5; i++) {
|
||||||
|
*point++ = yPoints[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destCurveData.type == CURVE_TYPE_CUSTOM) {
|
||||||
|
for (int i = 1; i < destCurveData.points + 4; i++) {
|
||||||
|
*point++ = yPoints[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storageDirty(EE_MODEL);
|
||||||
|
|
||||||
|
lua_pushinteger(L, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*luadoc
|
/*luadoc
|
||||||
@function model.getCustomFunction(function)
|
@function model.getCustomFunction(function)
|
||||||
|
|
||||||
|
@ -1132,6 +1323,7 @@ const luaL_Reg modelLib[] = {
|
||||||
{ "getCustomFunction", luaModelGetCustomFunction },
|
{ "getCustomFunction", luaModelGetCustomFunction },
|
||||||
{ "setCustomFunction", luaModelSetCustomFunction },
|
{ "setCustomFunction", luaModelSetCustomFunction },
|
||||||
{ "getCurve", luaModelGetCurve },
|
{ "getCurve", luaModelGetCurve },
|
||||||
|
{ "setCurve", luaModelSetCurve },
|
||||||
{ "getOutput", luaModelGetOutput },
|
{ "getOutput", luaModelGetOutput },
|
||||||
{ "setOutput", luaModelSetOutput },
|
{ "setOutput", luaModelSetOutput },
|
||||||
{ "getGlobalVariable", luaModelGetGlobalVariable },
|
{ "getGlobalVariable", luaModelGetGlobalVariable },
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue