1
0
Fork 0
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:
Arne Schwabe 2017-05-28 07:30:43 +02:00 committed by Bertrand Songis
parent 1cb0156cd0
commit cd23fedb56
3 changed files with 194 additions and 2 deletions

View file

@ -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

View file

@ -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

View file

@ -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 },