1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-15 12:25:12 +03:00
opentx/radio/src/lua/api_general.cpp
2016-05-09 19:29:52 +02:00

945 lines
28 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <ctype.h>
#include <stdio.h>
#include "opentx.h"
#include "stamp.h"
#include "lua/lua_api.h"
#if defined(PCBHORUS)
#include "lua/lua_exports_horus.inc" // this line must be after lua headers
#elif defined(PCBFLAMENCO)
#include "lua/lua_exports_flamenco.inc"
#elif defined(PCBTARANIS) && defined(REV9E)
#include "lua/lua_exports_taranis_x9e.inc"
#elif defined(PCBTARANIS)
#include "lua/lua_exports_taranis.inc"
#endif
#if defined(SIMU)
#define RADIO_VERSION FLAVOUR "-simu"
#else
#define RADIO_VERSION FLAVOUR
#endif
#define FIND_FIELD_DESC 0x01
/*luadoc
@function getVersion()
Return OpenTX version
@retval string OpenTX version (ie "2.1.5")
@retval multiple (available since 2.1.7) returns 5 values:
* (string) OpenTX version (ie "2.1.5")
* (string) radio version: `taranisx9e`, `taranisplus` or `taranis`.
If running in simulator the "-simu" is added
* (number) major version (ie 2 if version 2.1.5)
* (number) minor version (ie 1 if version 2.1.5)
* (number) revison number (ie 5 if version 2.1.5)
@status current Introduced in 2.0.0, expanded in 2.1.7
### Example
This example also runs in OpenTX versions where the function returned only one value:
```lua
local function run(event)
local ver, radio, maj, minor, rev = getVersion()
print("version: "..ver)
if radio then print ("radio: "..radio) end
if maj then print ("maj: "..maj) end
if minor then print ("minor: "..minor) end
if rev then print ("rev: "..rev) end
return 1
end
return { run=run }
```
Output of the above script in simulator:
```
version: 2.1.7
radio: taranis-simu
maj: 2
minor: 1
rev: 7
```
*/
static int luaGetVersion(lua_State *L)
{
lua_pushstring(L, VERSION);
lua_pushstring(L, RADIO_VERSION);
lua_pushnumber(L, VERSION_MAJOR);
lua_pushnumber(L, VERSION_MINOR);
lua_pushnumber(L, VERSION_REVISION);
return 5;
}
/*luadoc
@function getTime()
Return the time since the radio was started in multiple of 10ms
@retval number Number of 10ms ticks since the radio was started Example:
run time: 12.54 seconds, return value: 1254
@status current Introduced in 2.0.0
*/
static int luaGetTime(lua_State *L)
{
lua_pushunsigned(L, get_tmr10ms());
return 1;
}
static void luaPushDateTime(lua_State *L, uint32_t year, uint32_t mon, uint32_t day,
uint32_t hour, uint32_t min, uint32_t sec)
{
lua_createtable(L, 0, 6);
lua_pushtableinteger(L, "year", year);
lua_pushtableinteger(L, "mon", mon);
lua_pushtableinteger(L, "day", day);
lua_pushtableinteger(L, "hour", hour);
lua_pushtableinteger(L, "min", min);
lua_pushtableinteger(L, "sec", sec);
}
/*luadoc
@function getDateTime()
Return current system date and time that is kept by the RTC unit
@retval table current date and time, table elements:
* `year` (number) year
* `mon` (number) month
* `day` (number) day of month
* `hour` (number) hours
* `min` (number) minutes
* `sec` (number) seconds
*/
static int luaGetDateTime(lua_State *L)
{
struct gtm utm;
gettime(&utm);
luaPushDateTime(L, utm.tm_year + 1900, utm.tm_mon + 1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec);
return 1;
}
static void luaPushLatLon(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
/* result is lua table containing members ["lat"] and ["lon"] as lua_Number (doubles) in decimal degrees */
{
lua_createtable(L, 0, 4);
lua_pushtablenumber(L, "lat", telemetryItem.gps.latitude / 1000000.0);
lua_pushtablenumber(L, "pilot-lat", telemetryItem.pilotLatitude / 1000000.0);
lua_pushtablenumber(L, "lon", telemetryItem.gps.longitude / 1000000.0);
lua_pushtablenumber(L, "pilot-lon", telemetryItem.pilotLongitude / 1000000.0);
}
static void luaPushTelemetryDateTime(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
{
luaPushDateTime(L, telemetryItem.datetime.year + 2000, telemetryItem.datetime.month, telemetryItem.datetime.day,
telemetryItem.datetime.hour, telemetryItem.datetime.min, telemetryItem.datetime.sec);
}
static void luaPushCells(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
{
if (telemetryItem.cells.count == 0)
lua_pushinteger(L, (int)0); // returns zero if no cells
else {
lua_createtable(L, telemetryItem.cells.count, 0);
for (int i = 0; i < telemetryItem.cells.count; i++) {
lua_pushnumber(L, i + 1);
lua_pushnumber(L, telemetryItem.cells.values[i].value / 100.0);
lua_settable(L, -3);
}
}
}
void luaGetValueAndPush(int src)
{
getvalue_t value = getValue(src); // ignored for GPS, DATETIME, and CELLS
if (src >= MIXSRC_FIRST_TELEM && src <= MIXSRC_LAST_TELEM) {
src = (src-MIXSRC_FIRST_TELEM) / 3;
// telemetry values
if (TELEMETRY_STREAMING() && telemetryItems[src].isAvailable()) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[src];
switch (telemetrySensor.unit) {
case UNIT_GPS:
luaPushLatLon(telemetrySensor, telemetryItems[src]);
break;
case UNIT_DATETIME:
luaPushTelemetryDateTime(telemetrySensor, telemetryItems[src]);
break;
case UNIT_CELLS:
luaPushCells(telemetrySensor, telemetryItems[src]);
break;
default:
if (telemetrySensor.prec > 0)
lua_pushnumber(L, float(value)/telemetrySensor.getPrecDivisor());
else
lua_pushinteger(L, value);
break;
}
}
else {
// telemetry not working, return zero for telemetry sources
lua_pushinteger(L, (int)0);
}
}
else if (src == MIXSRC_TX_VOLTAGE) {
lua_pushnumber(L, float(value)/10.0);
}
else {
lua_pushinteger(L, value);
}
}
/**
Return field data for a given field name
*/
bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags)
{
// TODO better search method (binary lookup)
for (unsigned int n=0; n<DIM(luaSingleFields); ++n) {
if (!strcmp(name, luaSingleFields[n].name)) {
field.id = luaSingleFields[n].id;
if (flags & FIND_FIELD_DESC) {
strncpy(field.desc, luaSingleFields[n].desc, sizeof(field.desc)-1);
field.desc[sizeof(field.desc)-1] = '\0';
}
else {
field.desc[0] = '\0';
}
return true;
}
}
// search in multiples
unsigned int len = strlen(name);
for (unsigned int n=0; n<DIM(luaMultipleFields); ++n) {
const char * fieldName = luaMultipleFields[n].name;
unsigned int fieldLen = strlen(fieldName);
if (!strncmp(name, fieldName, fieldLen)) {
unsigned int index;
if (len == fieldLen+1 && isdigit(name[fieldLen])) {
index = name[fieldLen] - '1';
}
else if (len == fieldLen+2 && isdigit(name[fieldLen]) && isdigit(name[fieldLen+1])) {
index = 10 * (name[fieldLen] - '0') + (name[fieldLen+1] - '1');
}
else {
continue;
}
if (index < luaMultipleFields[n].count) {
field.id = luaMultipleFields[n].id + index;
if (flags & FIND_FIELD_DESC) {
snprintf(field.desc, sizeof(field.desc)-1, luaMultipleFields[n].desc, index+1);
field.desc[sizeof(field.desc)-1] = '\0';
}
else {
field.desc[0] = '\0';
}
return true;
}
}
}
// search in telemetry
field.desc[0] = '\0';
for (int i=0; i<MAX_SENSORS; i++) {
if (isTelemetryFieldAvailable(i)) {
char sensorName[TELEM_LABEL_LEN+1];
int len = zchar2str(sensorName, g_model.telemetrySensors[i].label, TELEM_LABEL_LEN);
if (!strncmp(sensorName, name, len)) {
if (name[len] == '\0') {
field.id = MIXSRC_FIRST_TELEM + 3*i;
field.desc[0] = '\0';
return true;
}
else if (name[len] == '-' && name[len+1] == '\0') {
field.id = MIXSRC_FIRST_TELEM + 3*i + 1;
field.desc[0] = '\0';
return true;
}
else if (name[len] == '+' && name[len+1] == '\0') {
field.id = MIXSRC_FIRST_TELEM + 3*i + 2;
field.desc[0] = '\0';
return true;
}
}
}
}
return false; // not found
}
static int luaTelemetryPop(lua_State *L)
{
if (!luaInputTelemetryFifo) {
luaInputTelemetryFifo = new Fifo<LuaTelemetryPacket, 16>();
if (!luaInputTelemetryFifo) {
return 0;
}
}
LuaTelemetryPacket packet;
if (luaInputTelemetryFifo->pop(packet)) {
lua_pushnumber(L, packet.physicalId);
lua_pushnumber(L, packet.primId);
lua_pushnumber(L, packet.dataId);
lua_pushunsigned(L, packet.value);
return 4;
}
return 0;
}
#define BIT(x, index) (((x) >> index) & 0x01)
uint8_t getDataId(uint8_t physicalId)
{
uint8_t result = physicalId;
result += (BIT(physicalId, 0) ^ BIT(physicalId, 1) ^ BIT(physicalId, 2)) << 5;
result += (BIT(physicalId, 2) ^ BIT(physicalId, 3) ^ BIT(physicalId, 4)) << 6;
result += (BIT(physicalId, 0) ^ BIT(physicalId, 2) ^ BIT(physicalId, 4)) << 7;
return result;
}
static int luaTelemetryPush(lua_State *L)
{
if (luaOutputTelemetryPacket.physicalId != 0x7E) {
lua_pushboolean(L, false);
return 1;
}
luaOutputTelemetryPacket.physicalId = getDataId(luaL_checkunsigned(L, 1));
luaOutputTelemetryPacket.primId = luaL_checkunsigned(L, 2);
luaOutputTelemetryPacket.dataId = luaL_checkunsigned(L, 3);
luaOutputTelemetryPacket.value = luaL_checkunsigned(L, 4);
lua_pushboolean(L, true);
return 1;
}
/*luadoc
@function getFieldInfo(name)
Return detailed information about field (source)
The list of valid sources is available:
* for OpenTX 2.0.x at http://downloads-20.open-tx.org/firmware/lua_fields.txt
* for OpenTX 2.1.x at http://downloads-21.open-tx.org/firmware/lua_fields.txt (depreciated)
* for OpenTX 2.1.x Taranis and Taranis Plus at http://downloads-21.open-tx.org/firmware/lua_fields_taranis.txt
* for OpenTX 2.1.x Taranis X9E at http://downloads-21.open-tx.org/firmware/lua_fields_taranis_x9e.txt
@param name (string) name of the field
@retval table information about requested field, table elements:
* `id` (number) field identifier
* `name` (string) field name
* `desc` (string) field description
@retval nil the requested field was not found
@status current Introduced in 2.0.8
*/
static int luaGetFieldInfo(lua_State *L)
{
const char * what = luaL_checkstring(L, 1);
LuaField field;
bool found = luaFindFieldByName(what, field, FIND_FIELD_DESC);
if (found) {
lua_newtable(L);
lua_pushtableinteger(L, "id", field.id);
lua_pushtablestring(L, "name", what);
lua_pushtablestring(L, "desc", field.desc);
return 1;
}
return 0;
}
/*luadoc
@function getValue(source)
Returns the value of a source.
The list of valid sources is available:
* for OpenTX 2.0.x at http://downloads-20.open-tx.org/firmware/lua_fields.txt
* for OpenTX 2.1.x at http://downloads-21.open-tx.org/firmware/lua_fields.txt
In OpenTX 2.1.x the telemetry sources no longer have a predefined name.
To get a telemetry value simply use it's sensor name. For example:
* Altitude sensor has a name "Alt"
* to get the current altitude use the source "Alt"
* to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"
@param source can be an identifier (number) (which was obtained by the getFieldInfo())
or a name (string) of the source.
@retval value current source value (number). Zero is returned for:
* non-existing sources
* for all telemetry source when the telemetry stream is not received
@retval table GPS position is returned in a table:
* `lat` (number) latitude, positive is North
* `lon` (number) longitude, positive is East
* `pilot-lat` (number) pilot latitude, positive is North
* `pilot-lon` (number) pilot longitude, positive is East
@retval table GPS date/time, see getDateTime()
@retval table Cells are returned in a table
(except where no cells were detected in which
case the returned value is 0):
* table has one item for each detected cell:
* key (number) cell number (1 to number of cells)
* value (number) current cell voltage
@status current Introduced in 2.0.0, changed in 2.1.0
@notice Getting a value by its numerical identifier is faster then by its name.
*/
static int luaGetValue(lua_State *L)
{
int src = 0;
if (lua_isnumber(L, 1)) {
src = luaL_checkinteger(L, 1);
}
else {
// convert from field name to its id
const char *name = luaL_checkstring(L, 1);
LuaField field;
bool found = luaFindFieldByName(name, field);
if (found) {
src = field.id;
}
}
luaGetValueAndPush(src);
return 1;
}
/*luadoc
@function getFlightMode(mode)
Return flight mode data.
@param mode (number) flight mode number to return (0 - 8). If mode parameter
is not specified (or contains invalid value), then the current flight mode data is returned.
@retval multiple returns 2 values:
* (number) (current) flight mode number (0 - 8)
* (string) (current) flight mode name
@status current Introduced in 2.1.7
*/
static int luaGetFlightMode(lua_State *L)
{
int mode = luaL_optinteger(L, 1, -1);
if (mode < 0 || mode >= MAX_FLIGHT_MODES) {
mode = mixerCurrentFlightMode;
}
lua_pushnumber(L, mode);
char name[sizeof(g_model.flightModeData[0].name)+1];
zchar2str(name, g_model.flightModeData[mode].name, sizeof(g_model.flightModeData[0].name));
lua_pushstring(L, name);
return 2;
}
/*luadoc
@function playFile(name)
Play a file from the SD card
@param path (string) full path to wav file (i.e. “/SOUNDS/en/system/tada.wav”)
Introduced in 2.1.0: If you use a relative path, the current language is appended
to the path (example: for English language: `/SOUNDS/en` is appended)
@status current Introduced in 2.0.0, changed in 2.1.0
*/
static int luaPlayFile(lua_State *L)
{
const char * filename = luaL_checkstring(L, 1);
if (filename[0] != '/') {
// relative sound file path - use current language dir for absolute path
char file[AUDIO_FILENAME_MAXLEN+1];
char * str = getAudioPath(file);
strncpy(str, filename, AUDIO_FILENAME_MAXLEN - (str-file));
file[AUDIO_FILENAME_MAXLEN] = 0;
PLAY_FILE(file, 0, 0);
}
else {
PLAY_FILE(filename, 0, 0);
}
return 0;
}
/*luadoc
@function playNumber(value, unit [, attributes])
Play a numerical value (text to speech)
@param value (number) number to play. Value is interpreted as integer.
@param unit (number) unit identifier (see table todo)
@param attributes (unsigned number) possible values:
* `0 or not present` plays integral part of the number (for a number 123 it plays 123)
* `PREC1` plays a number with one decimal place (for a number 123 it plays 12.3)
* `PREC2` plays a number with two decimal places (for a number 123 it plays 1.23)
@status current Introduced in 2.0.0
@notice 2.0 Only - automatic conversion of units for distance, speed, and temperature.
OpenTX 2.0:
| Unit | Sound | File (.wav) | Automatic conversion rules |
| --- | --- | --- | --- |
| 0 | --- | --- (no unit played) | |
| 1 | Volts | 116 | |
| 2 | Amps | 118 | |
| 3 | Meters per Second | 120 | |
| 4 | *missing file* | 122 | |
| 5 | Kilometers per Hour / Miles per Hour | 124 / 142 | Input value is KPH |
| 6 | Meters / Feet | 126 / 140 | Input value is meters |
| 7 | Degrees | 128 | Input value is celsius, converted to Fahrenheit for Imperial |
| 8 | Percent | 130 | |
| 9 | Milliamps | 132 | |
| 10 | Milliamp Hours | 134 | |
| 11 | Watts | 136 | |
| 12 | DB | 138 | |
| 13 | Feet | 140 | |
| 14 | Kilometers per Hour / Miles per Hour | 124 / 142 | Input value is in Knots, converted to KPH or MPH |
| 15 | Hours | 144 | |
| 16 | Minutes | 146 | |
| 17 | Seconds | 148 | |
| 18 | RPM | 150 | |
| 19 | Gee | 152 | |
| 20 | Degrees | 128 | |
OpenTX 2.1:
| 2.1 Unit | Sound | Sound File (.wav) |
| --- | --- | --- |
| 0 | --- | --- (no unit played) | |
| 1 | Volts | 116 |
| 2 | Amps | 118 |
| 3 | Milliamps | 120 |
| 4 | Knots | 122 |
| 5 | Meters per Second | 124 |
| 6 | Feet per Second | 126 |
| 7 | Kilometers per Hour | 128 |
| 8 | Miles per Hour | 130 |
| 9 | Meters | 132 |
| 10 | Feet | 134 |
| 11 | Degrees Celsius | 136 |
| 12 | Degrees Fahrenheit | 138 |
| 13 | Percent | 140 |
| 14 | Milliamp Hours | 142 |
| 15 | Watts | 144 |
| 16 | DB | 146 |
| 17 | RPM | 148 |
| 18 | Gee | 150 |
| 19 | Degrees | 152 |
| 20 | Milliliters | 154 |
| 21 | Fluid Ounces | 156 |
| 22 | Hours | 158 |
| 23 | Minutes | 160 |
| 24 | Seconds | 162 |
*/
static int luaPlayNumber(lua_State *L)
{
int number = luaL_checkinteger(L, 1);
int unit = luaL_checkinteger(L, 2);
unsigned int att = luaL_optunsigned(L, 3, 0);
playNumber(number, unit, att, 0);
return 0;
}
/*luadoc
@function playDuration(duration [, hourFormat])
Play a time value (text to speech)
@param duration (number) number of seconds to play. Only integral part is used.
@param hourFormat (number):
* `0 or not present` play format: minutes and seconds.
* `!= 0` play format: hours, minutes and seconds.
@status current Introduced in 2.1.0
*/
static int luaPlayDuration(lua_State *L)
{
int duration = luaL_checkinteger(L, 1);
bool playTime = (luaL_optinteger(L, 2, 0) != 0);
playDuration(duration, playTime ? PLAY_TIME : 0, 0);
return 0;
}
/*luadoc
@function playTone(frequency, duration, pause [, flags [, freqIncr]])
Play a tone
@param frequency (number) tone frequency in Hz (from 150 to 15000)
@param duration (number) length of the tone in milliseconds
@param pause (number) length of the silence after the tone in milliseconds
@param flags (number):
* `0 or not present` play with normal priority.
* `PLAY_BACKGROUND` play in background (built in vario function uses this context)
* `PLAY_NOW` play immediately
@param freqIncr (number) positive number increases the tone pitch (frequency with time),
negative number decreases it. The frequency changes every 10 milliseconds, the change is `freqIncr * 10Hz`.
The valid range is from -127 to 127.
@status current Introduced in 2.1.0
*/
static int luaPlayTone(lua_State *L)
{
int frequency = luaL_checkinteger(L, 1);
int length = luaL_checkinteger(L, 2);
int pause = luaL_checkinteger(L, 3);
int flags = luaL_optinteger(L, 4, 0);
int freqIncr = luaL_optinteger(L, 5, 0);
audioQueue.playTone(frequency, length, pause, flags, freqIncr);
return 0;
}
/*luadoc
@function killEvents(key)
Stops key state machine.
@param key (number) key to be killed, can also include event type (only key part is used)
@status current Introduced in 2.0.0
TODO table of events/masks
*/
static int luaKillEvents(lua_State *L)
{
uint8_t key = EVT_KEY_MASK(luaL_checkinteger(L, 1));
// prevent killing maskable keys (only in telemetry scripts)
// TODO add which tpye of script is running before p_call()
if (IS_MASKABLE(key)) {
killEvents(key);
}
return 0;
}
#if !defined(COLORLCD)
/*luadoc
@function GREY()
Returns gray value which can be used in LCD functions
@retval (number) a value that represents amount of *greyness* (from 0 to 15)
*/
static int luaGrey(lua_State *L)
{
int index = luaL_checkinteger(L, 1);
lua_pushunsigned(L, GREY(index));
return 1;
}
#endif
/*luadoc
@function getGeneralSettings()
Returns (some of) the general radio settings
@retval table with elements:
* `battMin` (number) radio battery range - minimum value
* `battMax` (number) radio battery range - maximum value
* `imperial` (number) set to a value different from 0 if the radio is set to the
IMPERIAL units
* `language` (string) radio language (used for menus)
* `voice` (string) voice language (used for speech)
@status current Introduced in 2.0.6, `imperial` added in TODO,
`language` and `voice` added int 2.2.0.
*/
static int luaGetGeneralSettings(lua_State *L)
{
lua_newtable(L);
lua_pushtablenumber(L, "battMin", double(90+g_eeGeneral.vBatMin)/10);
lua_pushtablenumber(L, "battMax", double(120+g_eeGeneral.vBatMax)/10);
lua_pushtableinteger(L, "imperial", g_eeGeneral.imperial);
lua_pushtablestring(L, "language", TRANSLATIONS);
lua_pushtablestring(L, "voice", currentLanguagePack->id);
return 1;
}
/*luadoc
@function popupInput(title, event, input, min, max)
Raises a pop-up on screen that allows uses input
@param title (string) text to display
@param event (number) the event variable that is passed in from the
Run function (key pressed)
@param input (number) value that can be adjusted by the +/­- keys
@param min (number) min value that input can reach (by pressing the -­ key)
@param max (number) max value that input can reach
@retval number result of the input adjustment
@retval "OK" user pushed ENT key
@retval "CANCEL" user pushed EXIT key
@notice Use only from stand-alone and telemetry scripts.
@status current Introduced in 2.0.0
*/
static int luaPopupInput(lua_State *L)
{
uint8_t event = luaL_checkinteger(L, 2);
warningInputValue = luaL_checkinteger(L, 3);
warningInputValueMin = luaL_checkinteger(L, 4);
warningInputValueMax = luaL_checkinteger(L, 5);
warningText = luaL_checkstring(L, 1);
warningType = WARNING_TYPE_INPUT;
displayWarning(event);
if (warningResult) {
warningResult = 0;
lua_pushstring(L, "OK");
}
else if (!warningText) {
lua_pushstring(L, "CANCEL");
}
else {
lua_pushinteger(L, warningInputValue);
}
warningText = NULL;
return 1;
}
/*luadoc
@function defaultStick(channel)
Get stick that is assigned to a channel. See Default Channel Order in General Settings.
@param channel (number) channel number (0 means CH1)
@retval number Stick assigned to this channel (from 0 to 3)
@status current Introduced in 2.0.0
*/
static int luaDefaultStick(lua_State *L)
{
uint8_t channel = luaL_checkinteger(L, 1);
lua_pushinteger(L, channel_order(channel+1)-1);
return 1;
}
/*luadoc
@function defaultChannel(stick)
Get channel assigned to stick. See Default Channel Order in General Settings
@param stick (number) stick number (from 0 to 3)
@retval number channel assigned to this stick (from 0 to 3)
@retval nil stick not found
@status current Introduced in 2.0.0
*/
static int luaDefaultChannel(lua_State *L)
{
uint8_t stick = luaL_checkinteger(L, 1);
for (int i=1; i<=4; i++) {
int tmp = channel_order(i) - 1;
if (tmp == stick) {
lua_pushinteger(L, i-1);
return 1;
}
}
lua_pushnil(L);
return 1;
}
const luaL_Reg opentxLib[] = {
{ "getTime", luaGetTime },
{ "getDateTime", luaGetDateTime },
{ "getVersion", luaGetVersion },
{ "getGeneralSettings", luaGetGeneralSettings },
{ "getValue", luaGetValue },
{ "getFieldInfo", luaGetFieldInfo },
{ "getFlightMode", luaGetFlightMode },
{ "playFile", luaPlayFile },
{ "playNumber", luaPlayNumber },
{ "playDuration", luaPlayDuration },
{ "playTone", luaPlayTone },
{ "popupInput", luaPopupInput },
{ "defaultStick", luaDefaultStick },
{ "defaultChannel", luaDefaultChannel },
{ "killEvents", luaKillEvents },
#if !defined(COLORLCD)
{ "GREY", luaGrey },
#endif
{ "telemetryPop", luaTelemetryPop },
{ "telemetryPush", luaTelemetryPush },
{ NULL, NULL } /* sentinel */
};
const luaR_value_entry opentxConstants[] = {
{ "FULLSCALE", RESX },
{ "XXLSIZE", XXLSIZE },
{ "DBLSIZE", DBLSIZE },
{ "MIDSIZE", MIDSIZE },
{ "SMLSIZE", SMLSIZE },
{ "INVERS", INVERS },
{ "BOLD", BOLD },
{ "BLINK", BLINK },
#if !defined(COLORLCD)
{ "FIXEDWIDTH", FIXEDWIDTH },
#endif
{ "LEFT", LEFT },
{ "PREC1", PREC1 },
{ "PREC2", PREC2 },
{ "VALUE", 0 }, // TODO reuse ZoneOption::Integer
{ "SOURCE", 1 }, // TODO reuse ZoneOption::Source
{ "REPLACE", MLTPX_REP },
{ "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT },
{ "MIXSRC_Rud", MIXSRC_Rud },
{ "MIXSRC_Ele", MIXSRC_Ele },
{ "MIXSRC_Thr", MIXSRC_Thr },
{ "MIXSRC_Ail", MIXSRC_Ail },
{ "MIXSRC_SA", MIXSRC_SA },
{ "MIXSRC_SB", MIXSRC_SB },
{ "MIXSRC_SC", MIXSRC_SC },
{ "MIXSRC_SD", MIXSRC_SD },
{ "MIXSRC_SE", MIXSRC_SE },
{ "MIXSRC_SF", MIXSRC_SF },
{ "MIXSRC_SG", MIXSRC_SG },
{ "MIXSRC_SH", MIXSRC_SH },
{ "MIXSRC_CH1", MIXSRC_CH1 },
{ "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH },
#if !defined(PCBHORUS)
{ "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU) },
#endif
#if defined(COLORLCD)
{ "COLOR", ZoneOption::Color },
{ "TEXT_COLOR_INDEX", TEXT_COLOR_INDEX },
{ "TEXT_BGCOLOR_INDEX", TEXT_BGCOLOR_INDEX },
{ "TEXT_INVERTED_COLOR_INDEX", TEXT_INVERTED_COLOR_INDEX },
{ "TEXT_INVERTED_BGCOLOR_INDEX", TEXT_INVERTED_BGCOLOR_INDEX },
{ "LINE_COLOR_INDEX", LINE_COLOR_INDEX },
{ "SCROLLBOX_COLOR_INDEX", SCROLLBOX_COLOR_INDEX },
{ "MENU_TITLE_BGCOLOR_INDEX", MENU_TITLE_BGCOLOR_INDEX },
{ "MENU_TITLE_COLOR_INDEX", MENU_TITLE_COLOR_INDEX },
{ "MENU_TITLE_DISABLE_COLOR_INDEX", MENU_TITLE_DISABLE_COLOR_INDEX },
{ "HEADER_COLOR_INDEX", HEADER_COLOR_INDEX },
{ "ALARM_COLOR_INDEX", ALARM_COLOR_INDEX },
{ "WARNING_COLOR_INDEX", WARNING_COLOR_INDEX },
{ "TEXT_DISABLE_COLOR_INDEX", TEXT_DISABLE_COLOR_INDEX },
{ "HEADER_COLOR_INDEX", HEADER_COLOR_INDEX },
{ "CURVE_AXIS_COLOR_INDEX", CURVE_AXIS_COLOR_INDEX },
{ "CURVE_COLOR_INDEX", CURVE_COLOR_INDEX },
{ "CURVE_CURSOR_COLOR_INDEX", CURVE_CURSOR_COLOR_INDEX },
{ "TITLE_BGCOLOR_INDEX", TITLE_BGCOLOR_INDEX },
{ "TRIM_BGCOLOR_INDEX", TRIM_BGCOLOR_INDEX },
{ "TRIM_SHADOW_COLOR_INDEX", TRIM_SHADOW_COLOR_INDEX },
{ "MAINVIEW_PANES_COLOR_INDEX", MAINVIEW_PANES_COLOR_INDEX },
{ "MAINVIEW_GRAPHICS_COLOR_INDEX", MAINVIEW_GRAPHICS_COLOR_INDEX },
{ "HEADER_BGCOLOR_INDEX", HEADER_BGCOLOR_INDEX },
{ "HEADER_ICON_BGCOLOR_INDEX", HEADER_ICON_BGCOLOR_INDEX },
{ "HEADER_CURRENT_BGCOLOR_INDEX", HEADER_CURRENT_BGCOLOR_INDEX },
{ "OVERLAY_COLOR_INDEX", OVERLAY_COLOR_INDEX },
{ "TEXT_COLOR", TEXT_COLOR },
{ "TEXT_BGCOLOR", TEXT_BGCOLOR },
{ "TEXT_INVERTED_COLOR", TEXT_INVERTED_COLOR },
{ "TEXT_INVERTED_BGCOLOR", TEXT_INVERTED_BGCOLOR },
{ "LINE_COLOR", LINE_COLOR },
{ "SCROLLBOX_COLOR", SCROLLBOX_COLOR },
{ "MENU_TITLE_BGCOLOR", MENU_TITLE_BGCOLOR },
{ "MENU_TITLE_COLOR", MENU_TITLE_COLOR },
{ "MENU_TITLE_DISABLE_COLOR", MENU_TITLE_DISABLE_COLOR },
{ "HEADER_COLOR", HEADER_COLOR },
{ "ALARM_COLOR", ALARM_COLOR },
{ "WARNING_COLOR", WARNING_COLOR },
{ "TEXT_DISABLE_COLOR", TEXT_DISABLE_COLOR },
{ "HEADER_COLOR", HEADER_COLOR },
{ "CURVE_AXIS_COLOR", CURVE_AXIS_COLOR },
{ "CURVE_COLOR", CURVE_COLOR },
{ "CURVE_CURSOR_COLOR", CURVE_CURSOR_COLOR },
{ "TITLE_BGCOLOR", TITLE_BGCOLOR },
{ "TRIM_BGCOLOR", TRIM_BGCOLOR },
{ "TRIM_SHADOW_COLOR", TRIM_SHADOW_COLOR },
{ "MAINVIEW_PANES_COLOR", MAINVIEW_PANES_COLOR },
{ "MAINVIEW_GRAPHICS_COLOR", MAINVIEW_GRAPHICS_COLOR },
{ "HEADER_BGCOLOR", HEADER_BGCOLOR },
{ "HEADER_ICON_BGCOLOR", HEADER_ICON_BGCOLOR },
{ "HEADER_CURRENT_BGCOLOR", HEADER_CURRENT_BGCOLOR },
{ "OVERLAY_COLOR", OVERLAY_COLOR },
{ "MENU_HEADER_HEIGHT", MENU_HEADER_HEIGHT },
{ "WHITE", (double)WHITE },
{ "GREY", (double)GREY },
{ "DARKGREY", (double)DARKGREY },
{ "BLACK", (double)BLACK },
{ "YELLOW", (double)YELLOW },
{ "BLUE", (double)BLUE },
{ "LIGHTGREY", (double)LIGHTGREY },
#endif
#if defined(PCBTARANIS)
{ "EVT_PAGE_BREAK", EVT_KEY_BREAK(KEY_PAGE) },
{ "EVT_PAGE_LONG", EVT_KEY_LONG(KEY_PAGE) },
{ "EVT_PLUS_BREAK", EVT_KEY_BREAK(KEY_PLUS) },
{ "EVT_MINUS_BREAK", EVT_KEY_BREAK(KEY_MINUS) },
{ "EVT_PLUS_FIRST", EVT_KEY_FIRST(KEY_PLUS) },
{ "EVT_MINUS_FIRST", EVT_KEY_FIRST(KEY_MINUS) },
{ "EVT_PLUS_REPT", EVT_KEY_REPT(KEY_PLUS) },
{ "EVT_MINUS_REPT", EVT_KEY_REPT(KEY_MINUS) },
{ "FILL_WHITE", FILL_WHITE },
{ "GREY_DEFAULT", GREY_DEFAULT },
{ "FORCE", FORCE },
{ "ERASE", ERASE },
{ "ROUND", ROUND },
#endif
{ "EVT_ENTER_BREAK", EVT_KEY_BREAK(KEY_ENTER) },
{ "EVT_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) },
{ "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT) },
{ "SOLID", SOLID },
{ "DOTTED", DOTTED },
{ "LCD_W", LCD_W },
{ "LCD_H", LCD_H },
{ "PLAY_NOW", PLAY_NOW },
{ "PLAY_BACKGROUND", PLAY_BACKGROUND },
{ "TIMEHOUR", TIMEHOUR },
{ NULL, 0 } /* sentinel */
};