mirror of
https://github.com/EdgeTX/edgetx.git
synced 2025-07-19 06:15:08 +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
|
@ -805,6 +805,9 @@ Get Curve parameters
|
|||
* `key` is point number (zero based)
|
||||
* `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
|
||||
*/
|
||||
static int luaModelGetCurve(lua_State *L)
|
||||
|
@ -849,6 +852,194 @@ static int luaModelGetCurve(lua_State *L)
|
|||
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
|
||||
@function model.getCustomFunction(function)
|
||||
|
||||
|
@ -1132,6 +1323,7 @@ const luaL_Reg modelLib[] = {
|
|||
{ "getCustomFunction", luaModelGetCustomFunction },
|
||||
{ "setCustomFunction", luaModelSetCustomFunction },
|
||||
{ "getCurve", luaModelGetCurve },
|
||||
{ "setCurve", luaModelSetCurve },
|
||||
{ "getOutput", luaModelGetOutput },
|
||||
{ "setOutput", luaModelSetOutput },
|
||||
{ "getGlobalVariable", luaModelGetGlobalVariable },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue