5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
25 #include "lua/lua_api.h"
26 #include "telemetry/frsky.h"
29 #include "lua/lua_exports_horus.inc" // this line must be after lua headers
30 #elif defined(PCBFLAMENCO)
31 #include "lua/lua_exports_flamenco.inc"
33 #include "lua/lua_exports_x9e.inc"
35 #include "lua/lua_exports_x7d.inc"
36 #elif defined(PCBTARANIS)
37 #include "lua/lua_exports_x9d.inc"
41 #define RADIO_VERSION FLAVOUR "-simu"
43 #define RADIO_VERSION FLAVOUR
46 #define FIND_FIELD_DESC 0x01
49 @function getVersion()
53 @retval string OpenTX version (ie "2.1.5")
55 @retval multiple (available since 2.1.7) returns 5 values:
56 * (string) OpenTX version (ie "2.1.5")
57 * (string) radio version: `taranisx9e`, `taranisplus` or `taranis`.
58 If running in simulator the "-simu" is added
59 * (number) major version (ie 2 if version 2.1.5)
60 * (number) minor version (ie 1 if version 2.1.5)
61 * (number) revison number (ie 5 if version 2.1.5)
63 @status current Introduced in 2.0.0, expanded in 2.1.7
67 This example also runs in OpenTX versions where the function returned only one value:
70 local function run(event)
71 local ver, radio, maj, minor, rev = getVersion()
72 print("version: "..ver)
73 if radio then print ("radio: "..radio) end
74 if maj then print ("maj: "..maj) end
75 if minor then print ("minor: "..minor) end
76 if rev then print ("rev: "..rev) end
82 Output of the above script in simulator:
91 static int luaGetVersion(lua_State
* L
)
93 lua_pushstring(L
, VERSION
);
94 lua_pushstring(L
, RADIO_VERSION
);
95 lua_pushnumber(L
, VERSION_MAJOR
);
96 lua_pushnumber(L
, VERSION_MINOR
);
97 lua_pushnumber(L
, VERSION_REVISION
);
104 Return the time since the radio was started in multiple of 10ms
106 @retval number Number of 10ms ticks since the radio was started Example:
107 run time: 12.54 seconds, return value: 1254
109 @status current Introduced in 2.0.0
111 static int luaGetTime(lua_State
* L
)
113 lua_pushunsigned(L
, get_tmr10ms());
117 static void luaPushDateTime(lua_State
* L
, uint32_t year
, uint32_t mon
, uint32_t day
,
118 uint32_t hour
, uint32_t min
, uint32_t sec
)
120 lua_createtable(L
, 0, 6);
121 lua_pushtableinteger(L
, "year", year
);
122 lua_pushtableinteger(L
, "mon", mon
);
123 lua_pushtableinteger(L
, "day", day
);
124 lua_pushtableinteger(L
, "hour", hour
);
125 lua_pushtableinteger(L
, "min", min
);
126 lua_pushtableinteger(L
, "sec", sec
);
130 @function getDateTime()
132 Return current system date and time that is kept by the RTC unit
134 @retval table current date and time, table elements:
135 * `year` (number) year
136 * `mon` (number) month
137 * `day` (number) day of month
138 * `hour` (number) hours
139 * `min` (number) minutes
140 * `sec` (number) seconds
142 static int luaGetDateTime(lua_State
* L
)
146 luaPushDateTime(L
, utm
.tm_year
+ TM_YEAR_BASE
, utm
.tm_mon
+ 1, utm
.tm_mday
, utm
.tm_hour
, utm
.tm_min
, utm
.tm_sec
);
150 static void luaPushLatLon(TelemetrySensor
& telemetrySensor
, TelemetryItem
& telemetryItem
)
151 /* result is lua table containing members ["lat"] and ["lon"] as lua_Number (doubles) in decimal degrees */
153 lua_createtable(L
, 0, 4);
154 lua_pushtablenumber(L
, "lat", telemetryItem
.gps
.latitude
/ 1000000.0);
155 lua_pushtablenumber(L
, "pilot-lat", telemetryItem
.pilotLatitude
/ 1000000.0);
156 lua_pushtablenumber(L
, "lon", telemetryItem
.gps
.longitude
/ 1000000.0);
157 lua_pushtablenumber(L
, "pilot-lon", telemetryItem
.pilotLongitude
/ 1000000.0);
160 static void luaPushTelemetryDateTime(TelemetrySensor
& telemetrySensor
, TelemetryItem
& telemetryItem
)
162 luaPushDateTime(L
, telemetryItem
.datetime
.year
, telemetryItem
.datetime
.month
, telemetryItem
.datetime
.day
,
163 telemetryItem
.datetime
.hour
, telemetryItem
.datetime
.min
, telemetryItem
.datetime
.sec
);
166 static void luaPushCells(TelemetrySensor
& telemetrySensor
, TelemetryItem
& telemetryItem
)
168 if (telemetryItem
.cells
.count
== 0)
169 lua_pushinteger(L
, (int)0); // returns zero if no cells
171 lua_createtable(L
, telemetryItem
.cells
.count
, 0);
172 for (int i
= 0; i
< telemetryItem
.cells
.count
; i
++) {
173 lua_pushnumber(L
, i
+ 1);
174 lua_pushnumber(L
, telemetryItem
.cells
.values
[i
].value
/ 100.0);
180 void luaGetValueAndPush(int src
)
182 getvalue_t value
= getValue(src
); // ignored for GPS, DATETIME, and CELLS
184 if (src
>= MIXSRC_FIRST_TELEM
&& src
<= MIXSRC_LAST_TELEM
) {
185 div_t qr
= div(src
-MIXSRC_FIRST_TELEM
, 3);
187 if (TELEMETRY_STREAMING() && telemetryItems
[qr
.quot
].isAvailable()) {
188 TelemetrySensor
& telemetrySensor
= g_model
.telemetrySensors
[qr
.quot
];
189 switch (telemetrySensor
.unit
) {
191 luaPushLatLon(telemetrySensor
, telemetryItems
[qr
.quot
]);
194 luaPushTelemetryDateTime(telemetrySensor
, telemetryItems
[qr
.quot
]);
198 luaPushCells(telemetrySensor
, telemetryItems
[qr
.quot
]);
201 // deliberate no break here to properly return `Cels-` and `Cels+`
203 if (telemetrySensor
.prec
> 0)
204 lua_pushnumber(L
, float(value
)/telemetrySensor
.getPrecDivisor());
206 lua_pushinteger(L
, value
);
211 // telemetry not working, return zero for telemetry sources
212 lua_pushinteger(L
, (int)0);
215 else if (src
== MIXSRC_TX_VOLTAGE
) {
216 lua_pushnumber(L
, float(value
)/10.0);
219 lua_pushinteger(L
, value
);
224 Return field data for a given field name
226 bool luaFindFieldByName(const char * name
, LuaField
& field
, unsigned int flags
)
228 // TODO better search method (binary lookup)
229 for (unsigned int n
=0; n
<DIM(luaSingleFields
); ++n
) {
230 if (!strcmp(name
, luaSingleFields
[n
].name
)) {
231 field
.id
= luaSingleFields
[n
].id
;
232 if (flags
& FIND_FIELD_DESC
) {
233 strncpy(field
.desc
, luaSingleFields
[n
].desc
, sizeof(field
.desc
)-1);
234 field
.desc
[sizeof(field
.desc
)-1] = '\0';
237 field
.desc
[0] = '\0';
243 // search in multiples
244 unsigned int len
= strlen(name
);
245 for (unsigned int n
=0; n
<DIM(luaMultipleFields
); ++n
) {
246 const char * fieldName
= luaMultipleFields
[n
].name
;
247 unsigned int fieldLen
= strlen(fieldName
);
248 if (!strncmp(name
, fieldName
, fieldLen
)) {
250 if (len
== fieldLen
+1 && isdigit(name
[fieldLen
])) {
251 index
= name
[fieldLen
] - '1';
253 else if (len
== fieldLen
+2 && isdigit(name
[fieldLen
]) && isdigit(name
[fieldLen
+1])) {
254 index
= 10 * (name
[fieldLen
] - '0') + (name
[fieldLen
+1] - '1');
259 if (index
< luaMultipleFields
[n
].count
) {
260 field
.id
= luaMultipleFields
[n
].id
+ index
;
261 if (flags
& FIND_FIELD_DESC
) {
262 snprintf(field
.desc
, sizeof(field
.desc
)-1, luaMultipleFields
[n
].desc
, index
+1);
263 field
.desc
[sizeof(field
.desc
)-1] = '\0';
266 field
.desc
[0] = '\0';
273 // search in telemetry
274 field
.desc
[0] = '\0';
275 for (int i
=0; i
<MAX_TELEMETRY_SENSORS
; i
++) {
276 if (isTelemetryFieldAvailable(i
)) {
277 char sensorName
[TELEM_LABEL_LEN
+1];
278 int len
= zchar2str(sensorName
, g_model
.telemetrySensors
[i
].label
, TELEM_LABEL_LEN
);
279 if (!strncmp(sensorName
, name
, len
)) {
280 if (name
[len
] == '\0') {
281 field
.id
= MIXSRC_FIRST_TELEM
+ 3*i
;
282 field
.desc
[0] = '\0';
285 else if (name
[len
] == '-' && name
[len
+1] == '\0') {
286 field
.id
= MIXSRC_FIRST_TELEM
+ 3*i
+ 1;
287 field
.desc
[0] = '\0';
290 else if (name
[len
] == '+' && name
[len
+1] == '\0') {
291 field
.id
= MIXSRC_FIRST_TELEM
+ 3*i
+ 2;
292 field
.desc
[0] = '\0';
299 return false; // not found
303 @function sportTelemetryPop()
305 Pops a received SPORT packet from the queue. Please note that only packets using a data ID within 0x5000 to 0x50FF (frame ID == 0x10), as well as packets with a frame ID equal 0x32 (regardless of the data ID) will be passed to the LUA telemetry receive queue.
307 @retval SPORT paket as a quadruple:
313 @status current Introduced in 2.2.0
315 static int luaSportTelemetryPop(lua_State
* L
)
317 if (!luaInputTelemetryFifo
) {
318 luaInputTelemetryFifo
= new Fifo
<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE
>();
319 if (!luaInputTelemetryFifo
) {
324 if (luaInputTelemetryFifo
->size() >= sizeof(SportTelemetryPacket
)) {
325 SportTelemetryPacket packet
;
326 for (uint8_t i
=0; i
<sizeof(packet
); i
++) {
327 luaInputTelemetryFifo
->pop(packet
.raw
[i
]);
329 lua_pushnumber(L
, packet
.physicalId
);
330 lua_pushnumber(L
, packet
.primId
);
331 lua_pushnumber(L
, packet
.dataId
);
332 lua_pushunsigned(L
, packet
.value
);
339 #define BIT(x, index) (((x) >> index) & 0x01)
340 uint8_t getDataId(uint8_t physicalId
)
342 uint8_t result
= physicalId
;
343 result
+= (BIT(physicalId
, 0) ^ BIT(physicalId
, 1) ^ BIT(physicalId
, 2)) << 5;
344 result
+= (BIT(physicalId
, 2) ^ BIT(physicalId
, 3) ^ BIT(physicalId
, 4)) << 6;
345 result
+= (BIT(physicalId
, 0) ^ BIT(physicalId
, 2) ^ BIT(physicalId
, 4)) << 7;
350 @function sportTelemetryPush()
352 This functions allows for sending SPORT telemetry data toward the receiver,
353 and more generally, to anything connected SPORT bus on the receiver or transmitter.
355 When called without parameters, it will only return the status of the ouput buffer without sending anything.
357 @param sensorId physical sensor ID
359 @param frameId frame ID
361 @param dataId data ID
365 @retval boolean data queued in output buffer or not.
367 @status current Introduced in 2.2.0
369 static int luaSportTelemetryPush(lua_State
* L
)
371 if (lua_gettop(L
) == 0) {
372 lua_pushboolean(L
, isSportOutputBufferAvailable());
374 else if (isSportOutputBufferAvailable()) {
375 SportTelemetryPacket packet
;
376 packet
.physicalId
= getDataId(luaL_checkunsigned(L
, 1));
377 packet
.primId
= luaL_checkunsigned(L
, 2);
378 packet
.dataId
= luaL_checkunsigned(L
, 3);
379 packet
.value
= luaL_checkunsigned(L
, 4);
380 sportOutputPushPacket(&packet
);
381 lua_pushboolean(L
, true);
384 lua_pushboolean(L
, false);
390 @function crossfireTelemetryPop()
392 @retval SPORT paket as a quadruple:
398 @status current Introduced in 2.2.0
400 static int luaCrossfireTelemetryPop(lua_State
* L
)
402 if (!luaInputTelemetryFifo
) {
403 luaInputTelemetryFifo
= new Fifo
<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE
>();
404 if (!luaInputTelemetryFifo
) {
409 uint8_t length
, data
;
410 if (luaInputTelemetryFifo
->probe(length
) && luaInputTelemetryFifo
->size() >= uint32_t(length
)) {
411 // length value includes the length field
412 luaInputTelemetryFifo
->pop(length
);
413 luaInputTelemetryFifo
->pop(data
); // command
414 lua_pushnumber(L
, data
);
416 for (uint8_t i
=1; i
<length
-1; i
++) {
417 luaInputTelemetryFifo
->pop(data
);
418 lua_pushinteger(L
, i
);
419 lua_pushinteger(L
, data
);
429 @function crossfireTelemetryPush()
431 This functions allows for sending telemetry data toward the TBS Crossfire link.
433 When called without parameters, it will only return the status of the ouput buffer without sending anything.
435 @param sensorId physical sensor ID
437 @param frameId frame ID
439 @param dataId data ID
443 @retval boolean data queued in output buffer or not.
445 @status current Introduced in 2.2.0
447 static int luaCrossfireTelemetryPush(lua_State
* L
)
449 if (lua_gettop(L
) == 0) {
450 lua_pushboolean(L
, isCrossfireOutputBufferAvailable());
452 else if (isCrossfireOutputBufferAvailable()) {
453 uint8_t command
= luaL_checkunsigned(L
, 1);
454 luaL_checktype(L
, 2, LUA_TTABLE
);
455 uint8_t length
= luaL_len(L
, 2);
456 telemetryOutputPushByte(MODULE_ADDRESS
);
457 telemetryOutputPushByte(2 + length
); // 1(COMMAND) + data length + 1(CRC)
458 telemetryOutputPushByte(command
); // COMMAND
459 for (int i
=0; i
<length
; i
++) {
460 lua_rawgeti(L
, 2, i
+1);
461 telemetryOutputPushByte(luaL_checkunsigned(L
, -1));
463 telemetryOutputPushByte(crc8(outputTelemetryBuffer
+2, 1 + length
));
464 telemetryOutputSetTrigger(command
);
465 lua_pushboolean(L
, true);
468 lua_pushboolean(L
, false);
474 @function getFieldInfo(name)
476 Return detailed information about field (source)
478 The list of valid sources is available:
479 * for OpenTX 2.0.x at http://downloads-20.open-tx.org/firmware/lua_fields.txt
480 * for OpenTX 2.1.x at http://downloads-21.open-tx.org/firmware/lua_fields.txt (depreciated)
481 * for OpenTX 2.1.x Taranis and Taranis Plus at http://downloads-21.open-tx.org/firmware/lua_fields_taranis.txt
482 * for OpenTX 2.1.x Taranis X9E at http://downloads-21.open-tx.org/firmware/lua_fields_taranis_x9e.txt
484 @param name (string) name of the field
486 @retval table information about requested field, table elements:
487 * `id` (number) field identifier
488 * `name` (string) field name
489 * `desc` (string) field description
491 @retval nil the requested field was not found
493 @status current Introduced in 2.0.8
495 static int luaGetFieldInfo(lua_State
* L
)
497 const char * what
= luaL_checkstring(L
, 1);
499 bool found
= luaFindFieldByName(what
, field
, FIND_FIELD_DESC
);
502 lua_pushtableinteger(L
, "id", field
.id
);
503 lua_pushtablestring(L
, "name", what
);
504 lua_pushtablestring(L
, "desc", field
.desc
);
511 @function getValue(source)
513 Returns the value of a source.
515 The list of valid sources is available:
516 * for OpenTX 2.0.x at http://downloads-20.open-tx.org/firmware/lua_fields.txt
517 * for OpenTX 2.1.x at http://downloads-21.open-tx.org/firmware/lua_fields.txt
519 In OpenTX 2.1.x the telemetry sources no longer have a predefined name.
520 To get a telemetry value simply use it's sensor name. For example:
521 * Altitude sensor has a name "Alt"
522 * to get the current altitude use the source "Alt"
523 * to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"
525 @param source can be an identifier (number) (which was obtained by the getFieldInfo())
526 or a name (string) of the source.
528 @retval value current source value (number). Zero is returned for:
529 * non-existing sources
530 * for all telemetry source when the telemetry stream is not received
532 @retval table GPS position is returned in a table:
533 * `lat` (number) latitude, positive is North
534 * `lon` (number) longitude, positive is East
535 * `pilot-lat` (number) pilot latitude, positive is North
536 * `pilot-lon` (number) pilot longitude, positive is East
538 @retval table GPS date/time, see getDateTime()
540 @retval table Cells are returned in a table
541 (except where no cells were detected in which
542 case the returned value is 0):
543 * table has one item for each detected cell:
544 * key (number) cell number (1 to number of cells)
545 * value (number) current cell voltage
547 @status current Introduced in 2.0.0, changed in 2.1.0, `Cels+` and
548 `Cels-` added in 2.1.9
550 @notice Getting a value by its numerical identifier is faster then by its name.
551 While `Cels` sensor returns current values of all cells in a table, a `Cels+` or
552 `Cels-` will return a single value - the maximum or minimum Cels value.
554 static int luaGetValue(lua_State
* L
)
557 if (lua_isnumber(L
, 1)) {
558 src
= luaL_checkinteger(L
, 1);
561 // convert from field name to its id
562 const char *name
= luaL_checkstring(L
, 1);
564 bool found
= luaFindFieldByName(name
, field
);
569 luaGetValueAndPush(src
);
576 Return the RAS value or nil if no valid hardware found
578 @retval number representing RAS value. Value bellow 0x33 (51 decimal) are all ok, value above 0x33 indicate a hardware antenna issue.
579 This is just a hardware pass/fail measure and does not represent the quality of the radio link
581 @status current Introduced in 2.2.0
583 static int luaGetRAS(lua_State
* L
)
585 if (IS_SWR_VALUE_VALID()) {
586 lua_pushinteger(L
, telemetryData
.swr
.value
);
596 @function getFlightMode(mode)
598 Return flight mode data.
600 @param mode (number) flight mode number to return (0 - 8). If mode parameter
601 is not specified (or contains invalid value), then the current flight mode data is returned.
603 @retval multiple returns 2 values:
604 * (number) (current) flight mode number (0 - 8)
605 * (string) (current) flight mode name
607 @status current Introduced in 2.1.7
609 static int luaGetFlightMode(lua_State
* L
)
611 int mode
= luaL_optinteger(L
, 1, -1);
612 if (mode
< 0 || mode
>= MAX_FLIGHT_MODES
) {
613 mode
= mixerCurrentFlightMode
;
615 lua_pushnumber(L
, mode
);
616 char name
[sizeof(g_model
.flightModeData
[0].name
)+1];
617 zchar2str(name
, g_model
.flightModeData
[mode
].name
, sizeof(g_model
.flightModeData
[0].name
));
618 lua_pushstring(L
, name
);
623 @function playFile(name)
625 Play a file from the SD card
627 @param path (string) full path to wav file (i.e. “/SOUNDS/en/system/tada.wav”)
628 Introduced in 2.1.0: If you use a relative path, the current language is appended
629 to the path (example: for English language: `/SOUNDS/en` is appended)
631 @status current Introduced in 2.0.0, changed in 2.1.0
633 static int luaPlayFile(lua_State
* L
)
635 const char * filename
= luaL_checkstring(L
, 1);
636 if (filename
[0] != '/') {
637 // relative sound file path - use current language dir for absolute path
638 char file
[AUDIO_FILENAME_MAXLEN
+1];
639 char * str
= getAudioPath(file
);
640 strncpy(str
, filename
, AUDIO_FILENAME_MAXLEN
- (str
-file
));
641 file
[AUDIO_FILENAME_MAXLEN
] = 0;
642 PLAY_FILE(file
, 0, 0);
645 PLAY_FILE(filename
, 0, 0);
651 @function playNumber(value, unit [, attributes])
653 Play a numerical value (text to speech)
655 @param value (number) number to play. Value is interpreted as integer.
657 @param unit (number) unit identifier (see table todo)
659 @param attributes (unsigned number) possible values:
660 * `0 or not present` plays integral part of the number (for a number 123 it plays 123)
661 * `PREC1` plays a number with one decimal place (for a number 123 it plays 12.3)
662 * `PREC2` plays a number with two decimal places (for a number 123 it plays 1.23)
664 @status current Introduced in 2.0.0
666 @notice 2.0 Only - automatic conversion of units for distance, speed, and temperature.
670 | Unit | Sound | File (.wav) | Automatic conversion rules |
671 | --- | --- | --- | --- |
672 | 0 | --- | --- (no unit played) | |
673 | 1 | Volts | 116 | |
675 | 3 | Meters per Second | 120 | |
676 | 4 | *missing file* | 122 | |
677 | 5 | Kilometers per Hour / Miles per Hour | 124 / 142 | Input value is KPH |
678 | 6 | Meters / Feet | 126 / 140 | Input value is meters |
679 | 7 | Degrees | 128 | Input value is celsius, converted to Fahrenheit for Imperial |
680 | 8 | Percent | 130 | |
681 | 9 | Milliamps | 132 | |
682 | 10 | Milliamp Hours | 134 | |
683 | 11 | Watts | 136 | |
685 | 13 | Feet | 140 | |
686 | 14 | Kilometers per Hour / Miles per Hour | 124 / 142 | Input value is in Knots, converted to KPH or MPH |
687 | 15 | Hours | 144 | |
688 | 16 | Minutes | 146 | |
689 | 17 | Seconds | 148 | |
692 | 20 | Degrees | 128 | |
697 | 2.1 Unit | Sound | Sound File (.wav) |
699 | 0 | --- | --- (no unit played) | |
702 | 3 | Milliamps | 120 |
704 | 5 | Meters per Second | 124 |
705 | 6 | Feet per Second | 126 |
706 | 7 | Kilometers per Hour | 128 |
707 | 8 | Miles per Hour | 130 |
710 | 11 | Degrees Celsius | 136 |
711 | 12 | Degrees Fahrenheit | 138 |
712 | 13 | Percent | 140 |
713 | 14 | Milliamp Hours | 142 |
718 | 19 | Degrees | 152 |
719 | 20 | Milliliters | 154 |
720 | 21 | Fluid Ounces | 156 |
722 | 23 | Minutes | 160 |
723 | 24 | Seconds | 162 |
726 static int luaPlayNumber(lua_State
* L
)
728 int number
= luaL_checkinteger(L
, 1);
729 int unit
= luaL_checkinteger(L
, 2);
730 unsigned int att
= luaL_optunsigned(L
, 3, 0);
731 playNumber(number
, unit
, att
, 0);
736 @function playDuration(duration [, hourFormat])
738 Play a time value (text to speech)
740 @param duration (number) number of seconds to play. Only integral part is used.
742 @param hourFormat (number):
743 * `0 or not present` play format: minutes and seconds.
744 * `!= 0` play format: hours, minutes and seconds.
746 @status current Introduced in 2.1.0
748 static int luaPlayDuration(lua_State
* L
)
750 int duration
= luaL_checkinteger(L
, 1);
751 bool playTime
= (luaL_optinteger(L
, 2, 0) != 0);
752 playDuration(duration
, playTime
? PLAY_TIME
: 0, 0);
757 @function playTone(frequency, duration, pause [, flags [, freqIncr]])
761 @param frequency (number) tone frequency in Hz (from 150 to 15000)
763 @param duration (number) length of the tone in milliseconds
765 @param pause (number) length of the silence after the tone in milliseconds
767 @param flags (number):
768 * `0 or not present` play with normal priority.
769 * `PLAY_BACKGROUND` play in background (built in vario function uses this context)
770 * `PLAY_NOW` play immediately
772 @param freqIncr (number) positive number increases the tone pitch (frequency with time),
773 negative number decreases it. The frequency changes every 10 milliseconds, the change is `freqIncr * 10Hz`.
774 The valid range is from -127 to 127.
776 @status current Introduced in 2.1.0
778 static int luaPlayTone(lua_State
* L
)
780 int frequency
= luaL_checkinteger(L
, 1);
781 int length
= luaL_checkinteger(L
, 2);
782 int pause
= luaL_checkinteger(L
, 3);
783 int flags
= luaL_optinteger(L
, 4, 0);
784 int freqIncr
= luaL_optinteger(L
, 5, 0);
785 audioQueue
.playTone(frequency
, length
, pause
, flags
, freqIncr
);
790 @function luaPlayHaptic(duration, pause [, flags])
792 Generate haptic feedback
794 @param duration (number) length of the haptic feedback in milliseconds
796 @param pause (number) length of the silence after haptic feedback in milliseconds
798 @param flags (number):
799 * `0 or not present` play with normal priority
800 * `PLAY_NOW` play immediately
802 @status current Introduced in 2.2.0
804 static int luaPlayHaptic(lua_State
* L
)
807 int length
= luaL_checkinteger(L
, 1);
808 int pause
= luaL_checkinteger(L
, 2);
809 int flags
= luaL_optinteger(L
, 3, 0);
810 haptic
.play(length
, pause
, flags
);
816 @function killEvents(key)
818 Stops key state machine.
820 @param key (number) key to be killed, can also include event type (only key part is used)
822 @status current Introduced in 2.0.0
824 TODO table of events/masks
826 static int luaKillEvents(lua_State
* L
)
828 uint8_t key
= EVT_KEY_MASK(luaL_checkinteger(L
, 1));
829 // prevent killing maskable keys (only in telemetry scripts)
830 // TODO add which tpye of script is running before p_call()
831 if (IS_MASKABLE(key
)) {
837 #if LCD_DEPTH > 1 && !defined(COLORLCD)
841 Returns gray value which can be used in LCD functions
843 @retval (number) a value that represents amount of *greyness* (from 0 to 15)
846 static int luaGrey(lua_State
* L
)
848 int index
= luaL_checkinteger(L
, 1);
849 lua_pushunsigned(L
, GREY(index
));
855 @function getGeneralSettings()
857 Returns (some of) the general radio settings
859 @retval table with elements:
860 * `battMin` (number) radio battery range - minimum value
861 * `battMax` (number) radio battery range - maximum value
862 * `imperial` (number) set to a value different from 0 if the radio is set to the
864 * `language` (string) radio language (used for menus)
865 * `voice` (string) voice language (used for speech)
867 @status current Introduced in 2.0.6, `imperial` added in TODO,
868 `language` and `voice` added int 2.2.0.
871 static int luaGetGeneralSettings(lua_State
* L
)
874 lua_pushtablenumber(L
, "battMin", double(90+g_eeGeneral
.vBatMin
)/10);
875 lua_pushtablenumber(L
, "battMax", double(120+g_eeGeneral
.vBatMax
)/10);
876 lua_pushtableinteger(L
, "imperial", g_eeGeneral
.imperial
);
877 lua_pushtablestring(L
, "language", TRANSLATIONS
);
878 lua_pushtablestring(L
, "voice", currentLanguagePack
->id
);
883 @function popupInput(title, event, input, min, max)
885 Raises a pop-up on screen that allows uses input
887 @param title (string) text to display
889 @param event (number) the event variable that is passed in from the
890 Run function (key pressed)
892 @param input (number) value that can be adjusted by the +/- keys
894 @param min (number) min value that input can reach (by pressing the - key)
896 @param max (number) max value that input can reach
898 @retval number result of the input adjustment
900 @retval "OK" user pushed ENT key
902 @retval "CANCEL" user pushed EXIT key
904 @notice Use only from stand-alone and telemetry scripts.
906 @status current Introduced in 2.0.0
908 static int luaPopupInput(lua_State
* L
)
910 event_t event
= luaL_checkinteger(L
, 2);
911 warningInputValue
= luaL_checkinteger(L
, 3);
912 warningInputValueMin
= luaL_checkinteger(L
, 4);
913 warningInputValueMax
= luaL_checkinteger(L
, 5);
914 warningText
= luaL_checkstring(L
, 1);
915 warningType
= WARNING_TYPE_INPUT
;
916 runPopupWarning(event
);
919 lua_pushstring(L
, "OK");
921 else if (!warningText
) {
922 lua_pushstring(L
, "CANCEL");
925 lua_pushinteger(L
, warningInputValue
);
932 @function popupWarning(title, event)
934 Raises a pop-up on screen that shows a warning
936 @param title (string) text to display
938 @param event (number) the event variable that is passed in from the
939 Run function (key pressed)
941 @retval "CANCEL" user pushed EXIT key
943 @notice Use only from stand-alone and telemetry scripts.
945 @status current Introduced in 2.2.0
947 static int luaPopupWarning(lua_State
* L
)
949 event_t event
= luaL_checkinteger(L
, 2);
950 warningText
= luaL_checkstring(L
, 1);
951 warningType
= WARNING_TYPE_ASTERISK
;
952 runPopupWarning(event
);
954 lua_pushstring(L
, "CANCEL");
964 @function popupConfirmation(title, event)
966 Raises a pop-up on screen that asks for confirmation
968 @param title (string) text to display
970 @param event (number) the event variable that is passed in from the
971 Run function (key pressed)
973 @retval "CANCEL" user pushed EXIT key
975 @notice Use only from stand-alone and telemetry scripts.
977 @status current Introduced in 2.2.0
979 static int luaPopupConfirmation(lua_State
* L
)
981 event_t event
= luaL_checkinteger(L
, 2);
982 warningText
= luaL_checkstring(L
, 1);
983 warningType
= WARNING_TYPE_CONFIRM
;
984 runPopupWarning(event
);
986 lua_pushstring(L
, warningResult
? "OK" : "CANCEL");
996 @function defaultStick(channel)
998 Get stick that is assigned to a channel. See Default Channel Order in General Settings.
1000 @param channel (number) channel number (0 means CH1)
1002 @retval number Stick assigned to this channel (from 0 to 3)
1004 @status current Introduced in 2.0.0
1006 static int luaDefaultStick(lua_State
* L
)
1008 uint8_t channel
= luaL_checkinteger(L
, 1);
1009 lua_pushinteger(L
, channel_order(channel
+1)-1);
1014 @function setTelemetryValue(id, subID, instance, value [, unit] [, precision [, name])
1016 @param id Id of the sensor
1018 @param subID subID of the sensor, usually 0
1020 @param instance instance of the sensor (SensorID)
1022 @param value fed to the sensor
1024 @param unit unit of the sensor.
1025 * `0 or not present` UNIT_RAW.
1026 * `!= 0` Valid values are 1 (UNIT_VOLTS), 2 (UNIT_AMPS), 3 (UNIT_MILLIAMPS),
1027 4 (UNIT_KTS), 5 (UNIT_METERS_PER_SECOND), 6 (UNIT_FEET_PER_SECOND), 7 (UNIT_KMH), 8 (UNIT_MPH), 9 (UNIT_METERS),
1028 10 (UNIT_FEET), 11 (UNIT_CELSIUS), 12 (UNIT_FAHRENHEIT), 13 (UNIT_PERCENT), 14 (UNIT_MAH), 15 (UNIT_WATTS),
1029 16 (UNIT_MILLIWATTS), 17 (UNIT_DB), 18 (UNIT_RPMS), 19 (UNIT_G), 20 (UNIT_DEGREE), 21 (UNIT_RADIANS),
1030 22 (UNIT_MILLILITERS), 23 (UNIT_FLOZ), 24 (UNIT_HOURS), 25 (UNIT_MINUTES), 26 (UNIT_SECONDS), 27 (UNIT_CELLS),
1031 28 (UNIT_DATETIME), 29 (UNIT_GPS), 30 (UNIT_BITFIELD), 31 (UNIT_TEXT)
1033 @param precision the precision of the sensor
1034 * `0 or not present` no decimal precision.
1035 * `!= 0` value is divided by 10^precision, e.g. value=1000, prec=2 => 10.00.
1037 @param name (string) Name of the sensor if it does not yet exist (4 chars).
1038 * `not present` Name defaults to the Id.
1039 * `present` Sensor takes name of the argument. Argument must have name surrounded by quotes: e.g., "Name"
1041 @retval true, if the sensor was just added. In this case the value is ignored (subsequent call will set the value)
1043 static int luaSetTelemetryValue(lua_State
* L
)
1045 uint16_t id
= luaL_checkinteger(L
, 1);
1046 uint8_t subId
= luaL_checkinteger(L
, 2);
1047 uint8_t instance
= luaL_checkinteger(L
, 3);
1048 int32_t value
= luaL_checkinteger(L
, 4);
1049 uint32_t unit
= luaL_optinteger(L
, 5, 0);
1050 uint32_t prec
= luaL_optinteger(L
, 6, 0);
1053 const char* name
= luaL_optstring(L
, 7, NULL
);
1055 str2zchar(zname
, name
, 4);
1057 zname
[0] = hex2zchar((id
& 0xf000) >> 12);
1058 zname
[1] = hex2zchar((id
& 0x0f00) >> 8);
1059 zname
[2] = hex2zchar((id
& 0x00f0) >> 4);
1060 zname
[3] = hex2zchar((id
& 0x000f) >> 0);
1063 int index
= setTelemetryValue(TELEM_PROTO_LUA
, id
, subId
, instance
, value
, unit
, prec
);
1065 TelemetrySensor
&telemetrySensor
= g_model
.telemetrySensors
[index
];
1066 telemetrySensor
.id
= id
;
1067 telemetrySensor
.subId
= subId
;
1068 telemetrySensor
.instance
= instance
;
1069 telemetrySensor
.init(zname
, unit
, prec
);
1070 lua_pushboolean(L
, true);
1072 lua_pushboolean(L
, false);
1078 @function defaultChannel(stick)
1080 Get channel assigned to stick. See Default Channel Order in General Settings
1082 @param stick (number) stick number (from 0 to 3)
1084 @retval number channel assigned to this stick (from 0 to 3)
1086 @retval nil stick not found
1088 @status current Introduced in 2.0.0
1090 static int luaDefaultChannel(lua_State
* L
)
1092 uint8_t stick
= luaL_checkinteger(L
, 1);
1093 for (int i
=1; i
<=4; i
++) {
1094 int tmp
= channel_order(i
) - 1;
1096 lua_pushinteger(L
, i
-1);
1107 Get RSSI value as well as low and critical RSSI alarm levels (in dB)
1109 @retval rssi RSSI value (0 if no link)
1111 @retval alarm_low Configured low RSSI alarm level
1113 @retval alarm_crit Configured critical RSSI alarm level
1115 @status current Introduced in 2.2.0
1117 static int luaGetRSSI(lua_State
* L
)
1119 lua_pushunsigned(L
, min((uint8_t)99, TELEMETRY_RSSI()));
1120 lua_pushunsigned(L
, getRssiAlarmValue(0));
1121 lua_pushunsigned(L
, getRssiAlarmValue(1));
1125 const luaL_Reg opentxLib
[] = {
1126 { "getTime", luaGetTime
},
1127 { "getDateTime", luaGetDateTime
},
1128 { "getVersion", luaGetVersion
},
1129 { "getGeneralSettings", luaGetGeneralSettings
},
1130 { "getValue", luaGetValue
},
1131 { "getRAS", luaGetRAS
},
1132 { "getFieldInfo", luaGetFieldInfo
},
1133 { "getFlightMode", luaGetFlightMode
},
1134 { "playFile", luaPlayFile
},
1135 { "playNumber", luaPlayNumber
},
1136 { "playDuration", luaPlayDuration
},
1137 { "playTone", luaPlayTone
},
1138 { "playHaptic", luaPlayHaptic
},
1139 { "popupInput", luaPopupInput
},
1140 { "popupWarning", luaPopupWarning
},
1141 { "popupConfirmation", luaPopupConfirmation
},
1142 { "defaultStick", luaDefaultStick
},
1143 { "defaultChannel", luaDefaultChannel
},
1144 { "getRSSI", luaGetRSSI
},
1145 { "killEvents", luaKillEvents
},
1146 #if LCD_DEPTH > 1 && !defined(COLORLCD)
1147 { "GREY", luaGrey
},
1149 { "sportTelemetryPop", luaSportTelemetryPop
},
1150 { "sportTelemetryPush", luaSportTelemetryPush
},
1151 { "setTelemetryValue", luaSetTelemetryValue
},
1152 #if defined(CROSSFIRE)
1153 { "crossfireTelemetryPop", luaCrossfireTelemetryPop
},
1154 { "crossfireTelemetryPush", luaCrossfireTelemetryPush
},
1156 { NULL
, NULL
} /* sentinel */
1159 const luaR_value_entry opentxConstants
[] = {
1160 { "FULLSCALE", RESX
},
1161 { "XXLSIZE", XXLSIZE
},
1162 { "DBLSIZE", DBLSIZE
},
1163 { "MIDSIZE", MIDSIZE
},
1164 { "SMLSIZE", SMLSIZE
},
1165 { "INVERS", INVERS
},
1172 { "VALUE", 0 }, // TODO reuse ZoneOption::Integer
1173 { "SOURCE", 1 }, // TODO reuse ZoneOption::Source
1174 { "REPLACE", MLTPX_REP
},
1175 { "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT
},
1176 { "MIXSRC_Rud", MIXSRC_Rud
},
1177 { "MIXSRC_Ele", MIXSRC_Ele
},
1178 { "MIXSRC_Thr", MIXSRC_Thr
},
1179 { "MIXSRC_Ail", MIXSRC_Ail
},
1180 { "MIXSRC_SA", MIXSRC_SA
},
1181 { "MIXSRC_SB", MIXSRC_SB
},
1182 { "MIXSRC_SC", MIXSRC_SC
},
1183 { "MIXSRC_SD", MIXSRC_SD
},
1184 #if !defined(PCBX7D)
1185 { "MIXSRC_SE", MIXSRC_SE
},
1186 { "MIXSRC_SG", MIXSRC_SG
},
1188 { "MIXSRC_SF", MIXSRC_SF
},
1189 { "MIXSRC_SH", MIXSRC_SH
},
1190 { "MIXSRC_CH1", MIXSRC_CH1
},
1191 { "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH
},
1192 #if defined(COLORLCD)
1193 { "COLOR", ZoneOption::Color
},
1194 { "CUSTOM_COLOR", CUSTOM_COLOR
},
1195 { "TEXT_COLOR", TEXT_COLOR
},
1196 { "TEXT_BGCOLOR", TEXT_BGCOLOR
},
1197 { "TEXT_INVERTED_COLOR", TEXT_INVERTED_COLOR
},
1198 { "TEXT_INVERTED_BGCOLOR", TEXT_INVERTED_BGCOLOR
},
1199 { "LINE_COLOR", LINE_COLOR
},
1200 { "SCROLLBOX_COLOR", SCROLLBOX_COLOR
},
1201 { "MENU_TITLE_BGCOLOR", MENU_TITLE_BGCOLOR
},
1202 { "MENU_TITLE_COLOR", MENU_TITLE_COLOR
},
1203 { "MENU_TITLE_DISABLE_COLOR", MENU_TITLE_DISABLE_COLOR
},
1204 { "ALARM_COLOR", ALARM_COLOR
},
1205 { "WARNING_COLOR", WARNING_COLOR
},
1206 { "TEXT_DISABLE_COLOR", TEXT_DISABLE_COLOR
},
1207 { "HEADER_COLOR", HEADER_COLOR
},
1208 { "CURVE_AXIS_COLOR", CURVE_AXIS_COLOR
},
1209 { "CURVE_COLOR", CURVE_COLOR
},
1210 { "CURVE_CURSOR_COLOR", CURVE_CURSOR_COLOR
},
1211 { "TITLE_BGCOLOR", TITLE_BGCOLOR
},
1212 { "TRIM_BGCOLOR", TRIM_BGCOLOR
},
1213 { "TRIM_SHADOW_COLOR", TRIM_SHADOW_COLOR
},
1214 { "MAINVIEW_PANES_COLOR", MAINVIEW_PANES_COLOR
},
1215 { "MAINVIEW_GRAPHICS_COLOR", MAINVIEW_GRAPHICS_COLOR
},
1216 { "HEADER_BGCOLOR", HEADER_BGCOLOR
},
1217 { "HEADER_ICON_BGCOLOR", HEADER_ICON_BGCOLOR
},
1218 { "HEADER_CURRENT_BGCOLOR", HEADER_CURRENT_BGCOLOR
},
1219 { "OVERLAY_COLOR", OVERLAY_COLOR
},
1220 { "MENU_HEADER_HEIGHT", MENU_HEADER_HEIGHT
},
1221 { "WHITE", (double)WHITE
},
1222 { "GREY", (double)GREY
},
1223 { "DARKGREY", (double)DARKGREY
},
1224 { "BLACK", (double)BLACK
},
1225 { "YELLOW", (double)YELLOW
},
1226 { "BLUE", (double)BLUE
},
1227 { "LIGHTGREY", (double)LIGHTGREY
},
1228 { "RED", (double)RED
},
1229 { "DARKRED", (double)DARKRED
},
1231 { "FIXEDWIDTH", FIXEDWIDTH
},
1233 #if defined(PCBHORUS)
1234 { "EVT_PAGEUP_FIRST", EVT_KEY_FIRST(KEY_PGUP
) },
1235 { "EVT_PAGEDN_FIRST", EVT_KEY_FIRST(KEY_PGDN
) },
1236 { "EVT_TELEM_FIRST", EVT_KEY_FIRST(KEY_TELEM
) },
1237 { "EVT_MODEL_FIRST", EVT_KEY_FIRST(KEY_MODEL
) },
1238 { "EVT_SYS_FIRST", EVT_KEY_FIRST(KEY_RADIO
) },
1239 { "EVT_RTN_FIRST", EVT_KEY_FIRST(KEY_EXIT
) },
1240 #elif defined(PCBTARANIS)
1241 { "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU
) },
1242 { "EVT_PAGE_BREAK", EVT_KEY_BREAK(KEY_PAGE
) },
1243 { "EVT_PAGE_LONG", EVT_KEY_LONG(KEY_PAGE
) },
1244 { "EVT_PLUS_BREAK", EVT_KEY_BREAK(KEY_PLUS
) },
1245 { "EVT_MINUS_BREAK", EVT_KEY_BREAK(KEY_MINUS
) },
1246 { "EVT_PLUS_FIRST", EVT_KEY_FIRST(KEY_PLUS
) },
1247 { "EVT_MINUS_FIRST", EVT_KEY_FIRST(KEY_MINUS
) },
1248 { "EVT_PLUS_REPT", EVT_KEY_REPT(KEY_PLUS
) },
1249 { "EVT_MINUS_REPT", EVT_KEY_REPT(KEY_MINUS
) },
1251 { "FILL_WHITE", FILL_WHITE
},
1252 { "GREY_DEFAULT", GREY_DEFAULT
},
1258 { "EVT_ENTER_BREAK", EVT_KEY_BREAK(KEY_ENTER
) },
1259 { "EVT_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER
) },
1260 { "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT
) },
1261 #if defined(ROTARY_ENCODER_NAVIGATION)
1262 { "EVT_ROT_BREAK", EVT_KEY_BREAK(KEY_ENTER
) },
1263 { "EVT_ROT_LONG", EVT_KEY_LONG(KEY_ENTER
) },
1264 { "EVT_ROT_LEFT", EVT_ROTARY_LEFT
},
1265 { "EVT_ROT_RIGHT", EVT_ROTARY_RIGHT
},
1268 { "DOTTED", DOTTED
},
1271 { "PLAY_NOW", PLAY_NOW
},
1272 { "PLAY_BACKGROUND", PLAY_BACKGROUND
},
1273 { "TIMEHOUR", TIMEHOUR
},
1275 #if defined(PCBHORUS)
1276 // Adding the unit consts for the set Telemetry function adds about 1k of flash usage
1277 {"UNIT_RAW", UNIT_RAW
},
1278 {"UNIT_VOLTS", UNIT_VOLTS
},
1279 {"UNIT_AMPS", UNIT_AMPS
},
1280 {"UNIT_MILLIAMPS", UNIT_MILLIAMPS
},
1281 {"UNIT_KTS", UNIT_KTS
},
1282 {"UNIT_METERS_PER_SECOND", UNIT_METERS_PER_SECOND
},
1283 {"UNIT_FEET_PER_SECOND", UNIT_FEET_PER_SECOND
},
1284 {"UNIT_KMH", UNIT_KMH
},
1285 {"UNIT_MPH", UNIT_MPH
},
1286 {"UNIT_METERS", UNIT_METERS
},
1287 {"UNIT_FEET", UNIT_FEET
},
1288 {"UNIT_CELSIUS", UNIT_CELSIUS
},
1289 {"UNIT_FAHRENHEIT", UNIT_FAHRENHEIT
},
1290 {"UNIT_PERCENT", UNIT_PERCENT
},
1291 {"UNIT_MAH", UNIT_MAH
},
1292 {"UNIT_WATTS", UNIT_WATTS
},
1293 {"UNIT_MILLIWATTS", UNIT_MILLIWATTS
},
1294 {"UNIT_DB", UNIT_DB
},
1295 {"UNIT_RPMS", UNIT_RPMS
},
1296 {"UNIT_G", UNIT_G
},
1297 {"UNIT_DEGREE", UNIT_DEGREE
},
1298 {"UNIT_RADIANS", UNIT_RADIANS
},
1299 {"UNIT_MILLILITERS", UNIT_MILLILITERS
},
1300 {"UNIT_FLOZ", UNIT_FLOZ
},
1301 {"UNIT_HOURS", UNIT_HOURS
},
1302 {"UNIT_MINUTES", UNIT_MINUTES
},
1303 {"UNIT_SECONDS", UNIT_SECONDS
},
1304 {"UNIT_CELLS", UNIT_CELLS
},
1305 {"UNIT_DATETIME", UNIT_DATETIME
},
1306 {"UNIT_GPS", UNIT_GPS
},
1307 {"UNIT_BITFIELD", UNIT_BITFIELD
},
1308 {"UNIT_TEXT", UNIT_TEXT
},
1310 { NULL
, 0 } /* sentinel */