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.
26 #include "telemetry/frsky.h"
29 #include "lua/lua_exports_x12s.inc" // this line must be after lua headers
31 #include "lua/lua_exports_x10.inc"
33 #include "lua/lua_exports_x9e.inc"
35 #include "lua/lua_exports_x7.inc"
36 #elif defined(PCBXLITE)
37 #include "lua/lua_exports_xlite.inc"
38 #elif defined(PCBTARANIS)
39 #include "lua/lua_exports_x9d.inc"
43 #define RADIO_VERSION FLAVOUR "-simu"
45 #define RADIO_VERSION FLAVOUR
48 #define FIND_FIELD_DESC 0x01
51 @function getVersion()
55 @retval string OpenTX version (ie "2.1.5")
57 @retval multiple (available since 2.1.7) returns 5 values:
58 * (string) OpenTX version (ie "2.1.5")
59 * (string) radio type: `x12s`, `x10`, `x9e`, `x9d+`, `x9d` or `x7`.
60 If running in simulator the "-simu" is added
61 * (number) major version (ie 2 if version 2.1.5)
62 * (number) minor version (ie 1 if version 2.1.5)
63 * (number) revision number (ie 5 if version 2.1.5)
65 @status current Introduced in 2.0.0, expanded in 2.1.7, radio type strings changed in 2.2.0
69 This example also runs in OpenTX versions where the function returned only one value:
72 local function run(event)
73 local ver, radio, maj, minor, rev = getVersion()
74 print("version: "..ver)
75 if radio then print ("radio: "..radio) end
76 if maj then print ("maj: "..maj) end
77 if minor then print ("minor: "..minor) end
78 if rev then print ("rev: "..rev) end
84 Output of the above script in simulator:
93 static int luaGetVersion(lua_State
* L
)
95 lua_pushstring(L
, VERSION
);
96 lua_pushstring(L
, RADIO_VERSION
);
97 lua_pushnumber(L
, VERSION_MAJOR
);
98 lua_pushnumber(L
, VERSION_MINOR
);
99 lua_pushnumber(L
, VERSION_REVISION
);
106 Return the time since the radio was started in multiple of 10ms
108 @retval number Number of 10ms ticks since the radio was started Example:
109 run time: 12.54 seconds, return value: 1254
111 The timer internally uses a 32-bit counter which is enough for 30 years so
112 overflows will not happen.
114 @status current Introduced in 2.0.0
116 static int luaGetTime(lua_State
* L
)
118 lua_pushunsigned(L
, get_tmr10ms());
122 static void luaPushDateTime(lua_State
* L
, uint32_t year
, uint32_t mon
, uint32_t day
,
123 uint32_t hour
, uint32_t min
, uint32_t sec
)
125 uint32_t hour12
= hour
;
130 else if (hour
> 12) {
133 lua_createtable(L
, 0, 8);
134 lua_pushtableinteger(L
, "year", year
);
135 lua_pushtableinteger(L
, "mon", mon
);
136 lua_pushtableinteger(L
, "day", day
);
137 lua_pushtableinteger(L
, "hour", hour
);
138 lua_pushtableinteger(L
, "min", min
);
139 lua_pushtableinteger(L
, "sec", sec
);
140 lua_pushtableinteger(L
, "hour12", hour12
);
142 lua_pushtablestring(L
, "suffix", "am");
145 lua_pushtablestring(L
, "suffix", "pm");
150 @function getDateTime()
152 Return current system date and time that is kept by the RTC unit
154 @retval table current date and time, table elements:
155 * `year` (number) year
156 * `mon` (number) month
157 * `day` (number) day of month
158 * `hour` (number) hours
159 * `hour12` (number) hours in US format
160 * `min` (number) minutes
161 * `sec` (number) seconds
162 * `suffix` (text) am or pm
164 static int luaGetDateTime(lua_State
* L
)
168 luaPushDateTime(L
, utm
.tm_year
+ TM_YEAR_BASE
, utm
.tm_mon
+ 1, utm
.tm_mday
, utm
.tm_hour
, utm
.tm_min
, utm
.tm_sec
);
173 @function getRtcTime()
175 Return current RTC system date as unix timstamp (in seconds since 1. Jan 1970)
177 Please note the RTC timestamp is kept internally as a 32bit integer, which will overflow
180 @retval number Number of seconds elapsed since 1. Jan 1970
184 static int luaGetRtcTime(lua_State
* L
)
186 lua_pushunsigned(L
, g_rtcTime
);
191 static void luaPushLatLon(lua_State
* L
, TelemetrySensor
& telemetrySensor
, TelemetryItem
& telemetryItem
)
192 /* result is lua table containing members ["lat"] and ["lon"] as lua_Number (doubles) in decimal degrees */
194 lua_createtable(L
, 0, 4);
195 lua_pushtablenumber(L
, "lat", telemetryItem
.gps
.latitude
* 0.000001); // floating point multiplication is faster than division
196 lua_pushtablenumber(L
, "pilot-lat", telemetryItem
.pilotLatitude
* 0.000001);
197 lua_pushtablenumber(L
, "lon", telemetryItem
.gps
.longitude
* 0.000001);
198 lua_pushtablenumber(L
, "pilot-lon", telemetryItem
.pilotLongitude
* 0.000001);
201 static void luaPushTelemetryDateTime(lua_State
* L
, TelemetrySensor
& telemetrySensor
, TelemetryItem
& telemetryItem
)
203 luaPushDateTime(L
, telemetryItem
.datetime
.year
, telemetryItem
.datetime
.month
, telemetryItem
.datetime
.day
,
204 telemetryItem
.datetime
.hour
, telemetryItem
.datetime
.min
, telemetryItem
.datetime
.sec
);
207 static void luaPushCells(lua_State
* L
, TelemetrySensor
& telemetrySensor
, TelemetryItem
& telemetryItem
)
209 if (telemetryItem
.cells
.count
== 0)
210 lua_pushinteger(L
, (int)0); // returns zero if no cells
212 lua_createtable(L
, telemetryItem
.cells
.count
, 0);
213 for (int i
= 0; i
< telemetryItem
.cells
.count
; i
++) {
214 lua_pushnumber(L
, i
+ 1);
215 lua_pushnumber(L
, telemetryItem
.cells
.values
[i
].value
* 0.01f
);
221 void luaGetValueAndPush(lua_State
* L
, int src
)
223 getvalue_t value
= getValue(src
); // ignored for GPS, DATETIME, and CELLS
225 if (src
>= MIXSRC_FIRST_TELEM
&& src
<= MIXSRC_LAST_TELEM
) {
226 div_t qr
= div(src
-MIXSRC_FIRST_TELEM
, 3);
228 if (TELEMETRY_STREAMING() && telemetryItems
[qr
.quot
].isAvailable()) {
229 TelemetrySensor
& telemetrySensor
= g_model
.telemetrySensors
[qr
.quot
];
230 switch (telemetrySensor
.unit
) {
232 luaPushLatLon(L
, telemetrySensor
, telemetryItems
[qr
.quot
]);
235 luaPushTelemetryDateTime(L
, telemetrySensor
, telemetryItems
[qr
.quot
]);
238 lua_pushstring(L
, telemetryItems
[qr
.quot
].text
);
242 luaPushCells(L
, telemetrySensor
, telemetryItems
[qr
.quot
]);
245 // deliberate no break here to properly return `Cels-` and `Cels+`
247 if (telemetrySensor
.prec
> 0)
248 lua_pushnumber(L
, float(value
)/telemetrySensor
.getPrecDivisor());
250 lua_pushinteger(L
, value
);
255 // telemetry not working, return zero for telemetry sources
256 lua_pushinteger(L
, (int)0);
259 else if (src
== MIXSRC_TX_VOLTAGE
) {
260 lua_pushnumber(L
, float(value
) * 0.1f
);
263 lua_pushinteger(L
, value
);
268 Return field data for a given field name
270 bool luaFindFieldByName(const char * name
, LuaField
& field
, unsigned int flags
)
272 // TODO better search method (binary lookup)
273 for (unsigned int n
=0; n
<DIM(luaSingleFields
); ++n
) {
274 if (!strcmp(name
, luaSingleFields
[n
].name
)) {
275 field
.id
= luaSingleFields
[n
].id
;
276 if (flags
& FIND_FIELD_DESC
) {
277 strncpy(field
.desc
, luaSingleFields
[n
].desc
, sizeof(field
.desc
)-1);
278 field
.desc
[sizeof(field
.desc
)-1] = '\0';
281 field
.desc
[0] = '\0';
287 // search in multiples
288 unsigned int len
= strlen(name
);
289 for (unsigned int n
=0; n
<DIM(luaMultipleFields
); ++n
) {
290 const char * fieldName
= luaMultipleFields
[n
].name
;
291 unsigned int fieldLen
= strlen(fieldName
);
292 if (!strncmp(name
, fieldName
, fieldLen
)) {
294 if (len
== fieldLen
+1 && isdigit(name
[fieldLen
])) {
295 index
= name
[fieldLen
] - '1';
297 else if (len
== fieldLen
+2 && isdigit(name
[fieldLen
]) && isdigit(name
[fieldLen
+1])) {
298 index
= 10 * (name
[fieldLen
] - '0') + (name
[fieldLen
+1] - '1');
303 if (index
< luaMultipleFields
[n
].count
) {
304 if(luaMultipleFields
[n
].id
== MIXSRC_FIRST_TELEM
)
305 field
.id
= luaMultipleFields
[n
].id
+ index
*3;
307 field
.id
= luaMultipleFields
[n
].id
+ index
;
308 if (flags
& FIND_FIELD_DESC
) {
309 snprintf(field
.desc
, sizeof(field
.desc
)-1, luaMultipleFields
[n
].desc
, index
+1);
310 field
.desc
[sizeof(field
.desc
)-1] = '\0';
313 field
.desc
[0] = '\0';
320 // search in telemetry
321 field
.desc
[0] = '\0';
322 for (int i
=0; i
<MAX_TELEMETRY_SENSORS
; i
++) {
323 if (isTelemetryFieldAvailable(i
)) {
324 char sensorName
[TELEM_LABEL_LEN
+1];
325 int len
= zchar2str(sensorName
, g_model
.telemetrySensors
[i
].label
, TELEM_LABEL_LEN
);
326 if (!strncmp(sensorName
, name
, len
)) {
327 if (name
[len
] == '\0') {
328 field
.id
= MIXSRC_FIRST_TELEM
+ 3*i
;
329 field
.desc
[0] = '\0';
332 else if (name
[len
] == '-' && name
[len
+1] == '\0') {
333 field
.id
= MIXSRC_FIRST_TELEM
+ 3*i
+ 1;
334 field
.desc
[0] = '\0';
337 else if (name
[len
] == '+' && name
[len
+1] == '\0') {
338 field
.id
= MIXSRC_FIRST_TELEM
+ 3*i
+ 2;
339 field
.desc
[0] = '\0';
346 return false; // not found
350 @function sportTelemetryPop()
352 Pops a received SPORT packet from the queue. Please note that only packets using a data ID within 0x5000 to 0x52FF
353 (frame ID == 0x10), as well as packets with a frame ID equal 0x32 (regardless of the data ID) will be passed to
354 the LUA telemetry receive queue.
356 @retval nil queue does not contain any (or enough) bytes to form a whole packet
358 @retval multiple returns 4 values:
364 @status current Introduced in 2.2.0
366 static int luaSportTelemetryPop(lua_State
* L
)
368 if (!luaInputTelemetryFifo
) {
369 luaInputTelemetryFifo
= new Fifo
<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE
>();
370 if (!luaInputTelemetryFifo
) {
375 if (luaInputTelemetryFifo
->size() >= sizeof(SportTelemetryPacket
)) {
376 SportTelemetryPacket packet
;
377 for (uint8_t i
=0; i
<sizeof(packet
); i
++) {
378 luaInputTelemetryFifo
->pop(packet
.raw
[i
]);
380 lua_pushnumber(L
, packet
.physicalId
);
381 lua_pushnumber(L
, packet
.primId
);
382 lua_pushnumber(L
, packet
.dataId
);
383 lua_pushunsigned(L
, packet
.value
);
390 #define BIT(x, index) (((x) >> index) & 0x01)
391 uint8_t getDataId(uint8_t physicalId
)
393 uint8_t result
= physicalId
;
394 result
+= (BIT(physicalId
, 0) ^ BIT(physicalId
, 1) ^ BIT(physicalId
, 2)) << 5;
395 result
+= (BIT(physicalId
, 2) ^ BIT(physicalId
, 3) ^ BIT(physicalId
, 4)) << 6;
396 result
+= (BIT(physicalId
, 0) ^ BIT(physicalId
, 2) ^ BIT(physicalId
, 4)) << 7;
401 @function sportTelemetryPush()
403 This functions allows for sending SPORT telemetry data toward the receiver,
404 and more generally, to anything connected SPORT bus on the receiver or transmitter.
406 When called without parameters, it will only return the status of the output buffer without sending anything.
408 @param sensorId physical sensor ID
410 @param frameId frame ID
412 @param dataId data ID
416 @retval boolean data queued in output buffer or not.
418 @status current Introduced in 2.2.0
420 static int luaSportTelemetryPush(lua_State
* L
)
422 if (lua_gettop(L
) == 0) {
423 lua_pushboolean(L
, isSportOutputBufferAvailable());
425 else if (isSportOutputBufferAvailable()) {
426 SportTelemetryPacket packet
;
427 packet
.physicalId
= getDataId(luaL_checkunsigned(L
, 1));
428 packet
.primId
= luaL_checkunsigned(L
, 2);
429 packet
.dataId
= luaL_checkunsigned(L
, 3);
430 packet
.value
= luaL_checkunsigned(L
, 4);
431 sportOutputPushPacket(&packet
);
432 lua_pushboolean(L
, true);
435 lua_pushboolean(L
, false);
441 @function crossfireTelemetryPop()
443 Pops a received Crossfire Telemetry packet from the queue.
445 @retval nil queue does not contain any (or enough) bytes to form a whole packet
447 @retval multiple returns 2 values:
449 * packet (table) data bytes
451 @status current Introduced in 2.2.0
453 static int luaCrossfireTelemetryPop(lua_State
* L
)
455 if (!luaInputTelemetryFifo
) {
456 luaInputTelemetryFifo
= new Fifo
<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE
>();
457 if (!luaInputTelemetryFifo
) {
462 uint8_t length
= 0, data
= 0;
463 if (luaInputTelemetryFifo
->probe(length
) && luaInputTelemetryFifo
->size() >= uint32_t(length
)) {
464 // length value includes the length field
465 luaInputTelemetryFifo
->pop(length
);
466 luaInputTelemetryFifo
->pop(data
); // command
467 lua_pushnumber(L
, data
);
469 for (uint8_t i
=1; i
<length
-1; i
++) {
470 luaInputTelemetryFifo
->pop(data
);
471 lua_pushinteger(L
, i
);
472 lua_pushinteger(L
, data
);
482 @function crossfireTelemetryPush()
484 This functions allows for sending telemetry data toward the TBS Crossfire link.
486 When called without parameters, it will only return the status of the output buffer without sending anything.
488 @param command command
490 @param data table of data bytes
492 @retval boolean data queued in output buffer or not.
494 @status current Introduced in 2.2.0
496 static int luaCrossfireTelemetryPush(lua_State
* L
)
498 if (lua_gettop(L
) == 0) {
499 lua_pushboolean(L
, isCrossfireOutputBufferAvailable());
501 else if (isCrossfireOutputBufferAvailable()) {
502 uint8_t command
= luaL_checkunsigned(L
, 1);
503 luaL_checktype(L
, 2, LUA_TTABLE
);
504 uint8_t length
= luaL_len(L
, 2);
505 telemetryOutputPushByte(MODULE_ADDRESS
);
506 telemetryOutputPushByte(2 + length
); // 1(COMMAND) + data length + 1(CRC)
507 telemetryOutputPushByte(command
); // COMMAND
508 for (int i
=0; i
<length
; i
++) {
509 lua_rawgeti(L
, 2, i
+1);
510 telemetryOutputPushByte(luaL_checkunsigned(L
, -1));
512 telemetryOutputPushByte(crc8(outputTelemetryBuffer
+2, 1 + length
));
513 telemetryOutputSetTrigger(command
);
514 lua_pushboolean(L
, true);
517 lua_pushboolean(L
, false);
523 @function getFieldInfo(name)
525 Return detailed information about field (source)
527 The list of valid sources is available:
529 | OpenTX Version | Radio |
530 |----------------|-------|
531 | 2.0 | [all](http://downloads-20.open-tx.org/firmware/lua_fields.txt) |
532 | 2.1 | [X9D and X9D+](http://downloads-21.open-tx.org/firmware/lua_fields_taranis.txt), [X9E](http://downloads-21.open-tx.org/firmware/lua_fields_taranis_x9e.txt) |
533 | 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x12s.txt) |
535 @param name (string) name of the field
537 @retval table information about requested field, table elements:
538 * `id` (number) field identifier
539 * `name` (string) field name
540 * `desc` (string) field description
541 * 'unit' (number) unit identifier [Full list](../appendix/units.html)
543 @retval nil the requested field was not found
545 @status current Introduced in 2.0.8, 'unit' field added in 2.2.0
547 static int luaGetFieldInfo(lua_State
* L
)
549 const char * what
= luaL_checkstring(L
, 1);
551 bool found
= luaFindFieldByName(what
, field
, FIND_FIELD_DESC
);
554 lua_pushtableinteger(L
, "id", field
.id
);
555 lua_pushtablestring(L
, "name", what
);
556 lua_pushtablestring(L
, "desc", field
.desc
);
557 if (field
.id
>= MIXSRC_FIRST_TELEM
&& field
.id
<= MIXSRC_LAST_TELEM
) {
558 TelemetrySensor
& telemetrySensor
= g_model
.telemetrySensors
[(int)((field
.id
-MIXSRC_FIRST_TELEM
)/3)];
559 lua_pushtableinteger(L
, "unit", telemetrySensor
.unit
);
562 lua_pushtablenil(L
, "unit");
570 @function getValue(source)
572 Returns the value of a source.
574 The list of fixed sources:
576 | OpenTX Version | Radio |
577 |----------------|-------|
578 | 2.0 | [all](http://downloads-20.open-tx.org/firmware/lua_fields.txt) |
579 | 2.1 | [X9D and X9D+](http://downloads-21.open-tx.org/firmware/lua_fields_taranis.txt), [X9E](http://downloads-21.open-tx.org/firmware/lua_fields_taranis_x9e.txt) |
580 | 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x12s.txt) |
583 In OpenTX 2.1.x the telemetry sources no longer have a predefined name.
584 To get a telemetry value simply use it's sensor name. For example:
585 * Altitude sensor has a name "Alt"
586 * to get the current altitude use the source "Alt"
587 * to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"
589 @param source can be an identifier (number) (which was obtained by the getFieldInfo())
590 or a name (string) of the source.
592 @retval value current source value (number). Zero is returned for:
593 * non-existing sources
594 * for all telemetry source when the telemetry stream is not received
595 * far all non allowed sensors while FAI MODE is active
597 @retval table GPS position is returned in a table:
598 * `lat` (number) latitude, positive is North
599 * `lon` (number) longitude, positive is East
600 * `pilot-lat` (number) pilot latitude, positive is North
601 * `pilot-lon` (number) pilot longitude, positive is East
603 @retval table GPS date/time, see getDateTime()
605 @retval table Cells are returned in a table
606 (except where no cells were detected in which
607 case the returned value is 0):
608 * table has one item for each detected cell:
609 * key (number) cell number (1 to number of cells)
610 * value (number) current cell voltage
612 @status current Introduced in 2.0.0, changed in 2.1.0, `Cels+` and
613 `Cels-` added in 2.1.9
615 @notice Getting a value by its numerical identifier is faster then by its name.
616 While `Cels` sensor returns current values of all cells in a table, a `Cels+` or
617 `Cels-` will return a single value - the maximum or minimum Cels value.
619 static int luaGetValue(lua_State
* L
)
622 if (lua_isnumber(L
, 1)) {
623 src
= luaL_checkinteger(L
, 1);
626 // convert from field name to its id
627 const char *name
= luaL_checkstring(L
, 1);
629 bool found
= luaFindFieldByName(name
, field
);
634 luaGetValueAndPush(L
, src
);
641 Return the RAS value or nil if no valid hardware found
643 @retval number representing RAS value. Value bellow 0x33 (51 decimal) are all ok, value above 0x33 indicate a hardware antenna issue.
644 This is just a hardware pass/fail measure and does not represent the quality of the radio link
646 @notice RAS was called SWR in the past
648 @status current Introduced in 2.2.0
650 static int luaGetRAS(lua_State
* L
)
652 if (IS_RAS_VALUE_VALID()) {
653 lua_pushinteger(L
, telemetryData
.swr
.value
);
664 Return the internal GPS position or nil if no valid hardware found
666 @retval table representing the current radio position
667 * `lat` (number) internal GPS latitude, positive is North
668 * `lon` (number) internal GPS longitude, positive is East
669 * 'numsat' (number) current number of sats locked in by the GPS sensor
670 * 'fix' (boolean) fix status
671 * 'alt' (number) internal GPS altitude in 0.1m
672 * 'speed' (number) internal GPSspeed in 0.1m/s
673 * 'heading' (number) internal GPS ground course estimation in degrees * 10
675 @status current Introduced in 2.2.2
677 static int luaGetTxGPS(lua_State
* L
)
679 #if defined(INTERNAL_GPS)
680 lua_createtable(L
, 0, 7);
681 lua_pushtablenumber(L
, "lat", gpsData
.latitude
* 0.000001);
682 lua_pushtablenumber(L
, "lon", gpsData
.longitude
* 0.000001);
683 lua_pushtableinteger(L
, "numsat", gpsData
.numSat
);
684 lua_pushtableinteger(L
, "alt", gpsData
.altitude
);
685 lua_pushtableinteger(L
, "speed", gpsData
.speed
);
686 lua_pushtableinteger(L
, "heading", gpsData
.groundCourse
);
688 lua_pushtableboolean(L
, "fix", true);
690 lua_pushtableboolean(L
, "fix", false);
699 @function getFlightMode(mode)
701 Return flight mode data.
703 @param mode (number) flight mode number to return (0 - 8). If mode parameter
704 is not specified (or contains invalid value), then the current flight mode data is returned.
706 @retval multiple returns 2 values:
707 * (number) (current) flight mode number (0 - 8)
708 * (string) (current) flight mode name
710 @status current Introduced in 2.1.7
712 static int luaGetFlightMode(lua_State
* L
)
714 int mode
= luaL_optinteger(L
, 1, -1);
715 if (mode
< 0 || mode
>= MAX_FLIGHT_MODES
) {
716 mode
= mixerCurrentFlightMode
;
718 lua_pushnumber(L
, mode
);
719 char name
[sizeof(g_model
.flightModeData
[0].name
)+1];
720 zchar2str(name
, g_model
.flightModeData
[mode
].name
, sizeof(g_model
.flightModeData
[0].name
));
721 lua_pushstring(L
, name
);
726 @function playFile(name)
728 Play a file from the SD card
730 @param path (string) full path to wav file (i.e. “/SOUNDS/en/system/tada.wav”)
731 Introduced in 2.1.0: If you use a relative path, the current language is appended
732 to the path (example: for English language: `/SOUNDS/en` is appended)
734 @status current Introduced in 2.0.0, changed in 2.1.0
736 static int luaPlayFile(lua_State
* L
)
738 const char * filename
= luaL_checkstring(L
, 1);
739 if (filename
[0] != '/') {
740 // relative sound file path - use current language dir for absolute path
741 char file
[AUDIO_FILENAME_MAXLEN
+1];
742 char * str
= getAudioPath(file
);
743 strncpy(str
, filename
, AUDIO_FILENAME_MAXLEN
- (str
-file
));
744 file
[AUDIO_FILENAME_MAXLEN
] = 0;
745 PLAY_FILE(file
, 0, 0);
748 PLAY_FILE(filename
, 0, 0);
754 @function playNumber(value, unit [, attributes])
756 Play a numerical value (text to speech)
758 @param value (number) number to play. Value is interpreted as integer.
760 @param unit (number) unit identifier [Full list]((../appendix/units.html))
762 @param attributes (unsigned number) possible values:
763 * `0 or not present` plays integral part of the number (for a number 123 it plays 123)
764 * `PREC1` plays a number with one decimal place (for a number 123 it plays 12.3)
765 * `PREC2` plays a number with two decimal places (for a number 123 it plays 1.23)
767 @status current Introduced in 2.0.0
770 static int luaPlayNumber(lua_State
* L
)
772 int number
= luaL_checkinteger(L
, 1);
773 int unit
= luaL_checkinteger(L
, 2);
774 unsigned int att
= luaL_optunsigned(L
, 3, 0);
775 playNumber(number
, unit
, att
, 0);
780 @function playDuration(duration [, hourFormat])
782 Play a time value (text to speech)
784 @param duration (number) number of seconds to play. Only integral part is used.
786 @param hourFormat (number):
787 * `0 or not present` play format: minutes and seconds.
788 * `!= 0` play format: hours, minutes and seconds.
790 @status current Introduced in 2.1.0
792 static int luaPlayDuration(lua_State
* L
)
794 int duration
= luaL_checkinteger(L
, 1);
795 bool playTime
= (luaL_optinteger(L
, 2, 0) != 0);
796 playDuration(duration
, playTime
? PLAY_TIME
: 0, 0);
801 @function playTone(frequency, duration, pause [, flags [, freqIncr]])
805 @param frequency (number) tone frequency in Hz (from 150 to 15000)
807 @param duration (number) length of the tone in milliseconds
809 @param pause (number) length of the silence after the tone in milliseconds
811 @param flags (number):
812 * `0 or not present` play with normal priority.
813 * `PLAY_BACKGROUND` play in background (built in vario function uses this context)
814 * `PLAY_NOW` play immediately
816 @param freqIncr (number) positive number increases the tone pitch (frequency with time),
817 negative number decreases it. The frequency changes every 10 milliseconds, the change is `freqIncr * 10Hz`.
818 The valid range is from -127 to 127.
820 @status current Introduced in 2.1.0
822 static int luaPlayTone(lua_State
* L
)
824 int frequency
= luaL_checkinteger(L
, 1);
825 int length
= luaL_checkinteger(L
, 2);
826 int pause
= luaL_checkinteger(L
, 3);
827 int flags
= luaL_optinteger(L
, 4, 0);
828 int freqIncr
= luaL_optinteger(L
, 5, 0);
829 audioQueue
.playTone(frequency
, length
, pause
, flags
, freqIncr
);
834 @function playHaptic(duration, pause [, flags])
836 Generate haptic feedback
838 @param duration (number) length of the haptic feedback in milliseconds
840 @param pause (number) length of the silence after haptic feedback in milliseconds
842 @param flags (number):
843 * `0 or not present` play with normal priority
844 * `PLAY_NOW` play immediately
846 @status current Introduced in 2.2.0
848 static int luaPlayHaptic(lua_State
* L
)
851 int length
= luaL_checkinteger(L
, 1);
852 int pause
= luaL_checkinteger(L
, 2);
853 int flags
= luaL_optinteger(L
, 3, 0);
854 haptic
.play(length
, pause
, flags
);
862 @function killEvents(key)
864 Stops key state machine. See [Key Events](../key_events.md) for the detailed description.
866 @param key (number) key to be killed, can also include event type (only the key part is used)
868 @status current Introduced in 2.0.0
871 static int luaKillEvents(lua_State
* L
)
873 uint8_t key
= EVT_KEY_MASK(luaL_checkinteger(L
, 1));
874 // prevent killing maskable keys (only in telemetry scripts)
875 // TODO add which tpye of script is running before p_call()
876 if (IS_MASKABLE(key
)) {
882 #if LCD_DEPTH > 1 && !defined(COLORLCD)
886 Returns gray value which can be used in LCD functions
888 @retval (number) a value that represents amount of *greyness* (from 0 to 15)
890 @notice Only available on Taranis
892 @status current Introduced in 2.0.13
894 static int luaGrey(lua_State
* L
)
896 int index
= luaL_checkinteger(L
, 1);
897 lua_pushunsigned(L
, GREY(index
));
903 @function getGeneralSettings()
905 Returns (some of) the general radio settings
907 @retval table with elements:
908 * `battWarn` (number) radio battery range - warning value
909 * `battMin` (number) radio battery range - minimum value
910 * `battMax` (number) radio battery range - maximum value
911 * `imperial` (number) set to a value different from 0 if the radio is set to the
913 * `language` (string) radio language (used for menus)
914 * `voice` (string) voice language (used for speech)
915 * `gtimer` (number) radio global timer in seconds (does not include current session)
917 @status current Introduced in 2.0.6, `imperial` added in TODO,
918 `language` and `voice` added in 2.2.0, gtimer added in 2.2.2.
921 static int luaGetGeneralSettings(lua_State
* L
)
924 lua_pushtablenumber(L
, "battWarn", (g_eeGeneral
.vBatWarn
) * 0.1f
);
925 lua_pushtablenumber(L
, "battMin", (90+g_eeGeneral
.vBatMin
) * 0.1f
);
926 lua_pushtablenumber(L
, "battMax", (120+g_eeGeneral
.vBatMax
) * 0.1f
);
927 lua_pushtableinteger(L
, "imperial", g_eeGeneral
.imperial
);
928 lua_pushtablestring(L
, "language", TRANSLATIONS
);
929 lua_pushtablestring(L
, "voice", currentLanguagePack
->id
);
930 lua_pushtableinteger(L
, "gtimer", g_eeGeneral
.globalTimer
);
935 @function popupInput(title, event, input, min, max)
937 Raises a pop-up on screen that allows uses input
939 @param title (string) text to display
941 @param event (number) the event variable that is passed in from the
942 Run function (key pressed)
944 @param input (number) value that can be adjusted by the +/- keys
946 @param min (number) min value that input can reach (by pressing the - key)
948 @param max (number) max value that input can reach
950 @retval number result of the input adjustment
952 @retval "OK" user pushed ENT key
954 @retval "CANCEL" user pushed EXIT key
956 @notice Use only from stand-alone and telemetry scripts.
958 @status current Introduced in 2.0.0
960 static int luaPopupInput(lua_State
* L
)
962 event_t event
= luaL_checkinteger(L
, 2);
963 warningInputValue
= luaL_checkinteger(L
, 3);
964 warningInputValueMin
= luaL_checkinteger(L
, 4);
965 warningInputValueMax
= luaL_checkinteger(L
, 5);
966 warningText
= luaL_checkstring(L
, 1);
967 warningType
= WARNING_TYPE_INPUT
;
968 runPopupWarning(event
);
971 lua_pushstring(L
, "OK");
973 else if (!warningText
) {
974 lua_pushstring(L
, "CANCEL");
977 lua_pushinteger(L
, warningInputValue
);
984 @function popupWarning(title, event)
986 Raises a pop-up on screen that shows a warning
988 @param title (string) text to display
990 @param event (number) the event variable that is passed in from the
991 Run function (key pressed)
993 @retval "CANCEL" user pushed EXIT key
995 @notice Use only from stand-alone and telemetry scripts.
997 @status current Introduced in 2.2.0
999 static int luaPopupWarning(lua_State
* L
)
1001 event_t event
= luaL_checkinteger(L
, 2);
1002 warningText
= luaL_checkstring(L
, 1);
1003 warningType
= WARNING_TYPE_ASTERISK
;
1004 runPopupWarning(event
);
1006 lua_pushstring(L
, "CANCEL");
1016 @function popupConfirmation(title, event)
1018 Raises a pop-up on screen that asks for confirmation
1020 @param title (string) text to display
1022 @param event (number) the event variable that is passed in from the
1023 Run function (key pressed)
1025 @retval "CANCEL" user pushed EXIT key
1027 @notice Use only from stand-alone and telemetry scripts.
1029 @status current Introduced in 2.2.0
1031 static int luaPopupConfirmation(lua_State
* L
)
1033 event_t event
= luaL_checkinteger(L
, 2);
1034 warningText
= luaL_checkstring(L
, 1);
1035 warningType
= WARNING_TYPE_CONFIRM
;
1036 runPopupWarning(event
);
1038 lua_pushstring(L
, warningResult
? "OK" : "CANCEL");
1048 @function defaultStick(channel)
1050 Get stick that is assigned to a channel. See Default Channel Order in General Settings.
1052 @param channel (number) channel number (0 means CH1)
1054 @retval number Stick assigned to this channel (from 0 to 3)
1056 @status current Introduced in 2.0.0
1058 static int luaDefaultStick(lua_State
* L
)
1060 uint8_t channel
= luaL_checkinteger(L
, 1);
1061 lua_pushinteger(L
, channel_order(channel
+1)-1);
1066 @function setTelemetryValue(id, subID, instance, value [, unit [, precision [, name]]])
1068 @param id Id of the sensor, valid range is from 0 to 0xFFFF
1070 @param subID subID of the sensor, usually 0, valid range is from 0 to 7
1072 @param instance instance of the sensor (SensorID), valid range is from 0 to 0xFF
1074 @param value fed to the sensor
1076 @param unit unit of the sensor [Full list](../appendix/units.html)
1078 @param precision the precision of the sensor
1079 * `0 or not present` no decimal precision.
1080 * `!= 0` value is divided by 10^precision, e.g. value=1000, prec=2 => 10.00.
1082 @param name (string) Name of the sensor if it does not yet exist (4 chars).
1083 * `not present` Name defaults to the Id.
1084 * `present` Sensor takes name of the argument. Argument must have name surrounded by quotes: e.g., "Name"
1086 @retval true, if the sensor was just added. In this case the value is ignored (subsequent call will set the value)
1088 @notice All three parameters `id`, `subID` and `instance` can't be zero at the same time. At least one of them
1089 must be different from zero.
1091 @status current Introduced in 2.2.0
1093 static int luaSetTelemetryValue(lua_State
* L
)
1095 uint16_t id
= luaL_checkunsigned(L
, 1);
1096 uint8_t subId
= luaL_checkunsigned(L
, 2) & 0x7;
1097 uint8_t instance
= luaL_checkunsigned(L
, 3);
1098 int32_t value
= luaL_checkinteger(L
, 4);
1099 uint32_t unit
= luaL_optunsigned(L
, 5, 0);
1100 uint32_t prec
= luaL_optunsigned(L
, 6, 0);
1103 const char* name
= luaL_optstring(L
, 7, NULL
);
1104 if (name
!= NULL
&& strlen(name
) > 0) {
1105 str2zchar(zname
, name
, 4);
1107 zname
[0] = hex2zchar((id
& 0xf000) >> 12);
1108 zname
[1] = hex2zchar((id
& 0x0f00) >> 8);
1109 zname
[2] = hex2zchar((id
& 0x00f0) >> 4);
1110 zname
[3] = hex2zchar((id
& 0x000f) >> 0);
1112 if (id
| subId
| instance
) {
1113 int index
= setTelemetryValue(TELEM_PROTO_LUA
, id
, subId
, instance
, value
, unit
, prec
);
1115 TelemetrySensor
&telemetrySensor
= g_model
.telemetrySensors
[index
];
1116 telemetrySensor
.id
= id
;
1117 telemetrySensor
.subId
= subId
;
1118 telemetrySensor
.instance
= instance
;
1119 telemetrySensor
.init(zname
, unit
, prec
);
1120 lua_pushboolean(L
, true);
1122 lua_pushboolean(L
, false);
1126 lua_pushboolean(L
, false);
1131 @function defaultChannel(stick)
1133 Get channel assigned to stick. See Default Channel Order in General Settings
1135 @param stick (number) stick number (from 0 to 3)
1137 @retval number channel assigned to this stick (from 0 to 3)
1139 @retval nil stick not found
1141 @status current Introduced in 2.0.0
1143 static int luaDefaultChannel(lua_State
* L
)
1145 uint8_t stick
= luaL_checkinteger(L
, 1);
1146 for (int i
=1; i
<=4; i
++) {
1147 int tmp
= channel_order(i
) - 1;
1149 lua_pushinteger(L
, i
-1);
1160 Get RSSI value as well as low and critical RSSI alarm levels (in dB)
1162 @retval rssi RSSI value (0 if no link)
1164 @retval alarm_low Configured low RSSI alarm level
1166 @retval alarm_crit Configured critical RSSI alarm level
1168 @status current Introduced in 2.2.0
1170 static int luaGetRSSI(lua_State
* L
)
1172 lua_pushunsigned(L
, min((uint8_t)99, TELEMETRY_RSSI()));
1173 lua_pushunsigned(L
, g_model
.rssiAlarms
.getWarningRssi());
1174 lua_pushunsigned(L
, g_model
.rssiAlarms
.getCriticalRssi());
1179 @function loadScript(file [, mode], [,env])
1181 Load a Lua script file. This is similar to Lua's own [loadfile()](https://www.lua.org/manual/5.2/manual.html#pdf-loadfile)
1182 API method, but it uses OpenTx's optional pre-compilation feature to save memory and time during load.
1184 Return values are same as from Lua API loadfile() method: If the script was loaded w/out errors
1185 then the loaded script (or "chunk") is returned as a function. Otherwise, returns nil plus the error message.
1187 @param file (string) Full path and file name of script. The file extension is optional and ignored (see `mode` param to control
1188 which extension will be used). However, if an extension is specified, it should be ".lua" (or ".luac"), otherwise it is treated
1189 as part of the file name and the .lua/.luac will be appended to that.
1191 @param mode (string) (optional) Controls whether to force loading the text (.lua) or pre-compiled binary (.luac)
1192 version of the script. By default OTx will load the newest version and compile a new binary if necessary (overwriting any
1193 existing .luac version of the same script, and stripping some debug info like line numbers).
1194 You can use `mode` to control the loading behavior more specifically. Possible values are:
1197 * `T` (default on simulator) prefer text but load binary if that is the only version available.
1198 * `bt` (default on radio) either binary or text, whichever is newer (binary preferred when timestamps are equal).
1199 * Add `x` to avoid automatic compilation of source file to .luac version.
1200 Eg: "tx", "bx", or "btx".
1201 * Add `c` to force compilation of source file to .luac version (even if existing version is newer than source file).
1202 Eg: "tc" or "btc" (forces "t", overrides "x").
1203 * Add `d` to keep extra debug info in the compiled binary.
1204 Eg: "td", "btd", or "tcd" (no effect with just "b" or with "x").
1207 Note that you will get an error if you specify `mode` as "b" or "t" and that specific version of the file does not exist (eg. no .luac file when "b" is used).
1208 Also note that `mode` is NOT passed on to Lua's loader function, so unlike with loadfile() the actual file content is not checked (as if no mode or "bt" were passed to loadfile()).
1210 @param env (integer) See documentation for Lua function loadfile().
1212 @retval function The loaded script, or `nil` if there was an error (e.g. file not found or syntax error).
1214 @retval string Error message(s), if any. Blank if no error occurred.
1216 @status current Introduced in 2.2.0
1221 fun, err = loadScript("/SCRIPTS/FUNCTIONS/print.lua")
1222 if (fun ~= nil) then
1223 fun("Hello from loadScript()")
1230 static int luaLoadScript(lua_State
* L
)
1232 // this function is replicated pretty much verbatim from luaB_loadfile() and load_aux() in lbaselib.c
1233 const char *fname
= luaL_optstring(L
, 1, NULL
);
1234 const char *mode
= luaL_optstring(L
, 2, NULL
);
1235 int env
= (!lua_isnone(L
, 3) ? 3 : 0); // 'env' index or 0 if no 'env'
1237 if (fname
!= NULL
&& luaLoadScriptFileToState(L
, fname
, mode
) == SCRIPT_OK
) {
1238 if (env
!= 0) { // 'env' parameter?
1239 lua_pushvalue(L
, env
); // environment for loaded function
1240 if (!lua_setupvalue(L
, -2, 1)) // set it as 1st upvalue
1241 lua_pop(L
, 1); // remove 'env' if not used by previous call
1246 // error (message should be on top of the stack)
1247 if (!lua_isstring(L
, -1)) {
1248 // probably didn't find a file or had some other error before luaL_loadfile() was run
1249 lua_pushfstring(L
, "loadScript(\"%s\", \"%s\") error: File not found", (fname
!= NULL
? fname
: "nul"), (mode
!= NULL
? mode
: "bt"));
1252 lua_insert(L
, -2); // move nil before error message
1253 return 2; // return nil plus error message
1258 @function getUsage()
1260 Get percent of already used Lua instructions in current script execution cycle.
1262 @retval usage (number) a value from 0 to 100 (percent)
1264 @status current Introduced in 2.2.1
1266 static int luaGetUsage(lua_State
* L
)
1268 lua_pushinteger(L
, instructionsPercent
);
1273 @function resetGlobalTimer()
1275 Resets the radio global timer to 0.
1277 @status current Introduced in 2.2.2
1279 static int luaResetGlobalTimer(lua_State
* L
)
1281 g_eeGeneral
.globalTimer
= 0;
1282 storageDirty(EE_GENERAL
);
1286 const luaL_Reg opentxLib
[] = {
1287 { "getTime", luaGetTime
},
1288 { "getDateTime", luaGetDateTime
},
1289 #if defined(RTCLOCK)
1290 { "getRtcTime", luaGetRtcTime
},
1292 { "getVersion", luaGetVersion
},
1293 { "getGeneralSettings", luaGetGeneralSettings
},
1294 { "getValue", luaGetValue
},
1295 { "getRAS", luaGetRAS
},
1296 { "getTxGPS", luaGetTxGPS
},
1297 { "getFieldInfo", luaGetFieldInfo
},
1298 { "getFlightMode", luaGetFlightMode
},
1299 { "playFile", luaPlayFile
},
1300 { "playNumber", luaPlayNumber
},
1301 { "playDuration", luaPlayDuration
},
1302 { "playTone", luaPlayTone
},
1303 { "playHaptic", luaPlayHaptic
},
1304 { "popupInput", luaPopupInput
},
1305 { "popupWarning", luaPopupWarning
},
1306 { "popupConfirmation", luaPopupConfirmation
},
1307 { "defaultStick", luaDefaultStick
},
1308 { "defaultChannel", luaDefaultChannel
},
1309 { "getRSSI", luaGetRSSI
},
1310 { "killEvents", luaKillEvents
},
1311 { "loadScript", luaLoadScript
},
1312 { "getUsage", luaGetUsage
},
1313 { "resetGlobalTimer", luaResetGlobalTimer
},
1314 #if LCD_DEPTH > 1 && !defined(COLORLCD)
1315 { "GREY", luaGrey
},
1317 { "sportTelemetryPop", luaSportTelemetryPop
},
1318 { "sportTelemetryPush", luaSportTelemetryPush
},
1319 { "setTelemetryValue", luaSetTelemetryValue
},
1320 #if defined(CROSSFIRE)
1321 { "crossfireTelemetryPop", luaCrossfireTelemetryPop
},
1322 { "crossfireTelemetryPush", luaCrossfireTelemetryPush
},
1324 { NULL
, NULL
} /* sentinel */
1327 const luaR_value_entry opentxConstants
[] = {
1328 { "FULLSCALE", RESX
},
1329 { "XXLSIZE", XXLSIZE
},
1330 { "DBLSIZE", DBLSIZE
},
1331 { "MIDSIZE", MIDSIZE
},
1332 { "SMLSIZE", SMLSIZE
},
1333 { "INVERS", INVERS
},
1340 { "VALUE", INPUT_TYPE_VALUE
},
1341 { "SOURCE", INPUT_TYPE_SOURCE
},
1342 { "REPLACE", MLTPX_REP
},
1343 { "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT
},
1344 { "MIXSRC_Rud", MIXSRC_Rud
},
1345 { "MIXSRC_Ele", MIXSRC_Ele
},
1346 { "MIXSRC_Thr", MIXSRC_Thr
},
1347 { "MIXSRC_Ail", MIXSRC_Ail
},
1348 { "MIXSRC_SA", MIXSRC_SA
},
1349 { "MIXSRC_SB", MIXSRC_SB
},
1350 { "MIXSRC_SC", MIXSRC_SC
},
1351 { "MIXSRC_SD", MIXSRC_SD
},
1352 #if !defined(PCBX7) && !defined(PCBXLITE)
1353 { "MIXSRC_SE", MIXSRC_SE
},
1354 { "MIXSRC_SG", MIXSRC_SG
},
1356 #if !defined(PCBXLITE)
1357 { "MIXSRC_SF", MIXSRC_SF
},
1358 { "MIXSRC_SH", MIXSRC_SH
},
1360 { "MIXSRC_CH1", MIXSRC_CH1
},
1361 { "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH
},
1362 #if defined(COLORLCD)
1363 { "SHADOWED", SHADOWED
},
1364 { "COLOR", ZoneOption::Color
},
1365 { "BOOL", ZoneOption::Bool
},
1366 { "CUSTOM_COLOR", CUSTOM_COLOR
},
1367 { "TEXT_COLOR", TEXT_COLOR
},
1368 { "TEXT_BGCOLOR", TEXT_BGCOLOR
},
1369 { "TEXT_INVERTED_COLOR", TEXT_INVERTED_COLOR
},
1370 { "TEXT_INVERTED_BGCOLOR", TEXT_INVERTED_BGCOLOR
},
1371 { "LINE_COLOR", LINE_COLOR
},
1372 { "SCROLLBOX_COLOR", SCROLLBOX_COLOR
},
1373 { "MENU_TITLE_BGCOLOR", MENU_TITLE_BGCOLOR
},
1374 { "MENU_TITLE_COLOR", MENU_TITLE_COLOR
},
1375 { "MENU_TITLE_DISABLE_COLOR", MENU_TITLE_DISABLE_COLOR
},
1376 { "ALARM_COLOR", ALARM_COLOR
},
1377 { "WARNING_COLOR", WARNING_COLOR
},
1378 { "TEXT_DISABLE_COLOR", TEXT_DISABLE_COLOR
},
1379 { "HEADER_COLOR", HEADER_COLOR
},
1380 { "CURVE_AXIS_COLOR", CURVE_AXIS_COLOR
},
1381 { "CURVE_COLOR", CURVE_COLOR
},
1382 { "CURVE_CURSOR_COLOR", CURVE_CURSOR_COLOR
},
1383 { "TITLE_BGCOLOR", TITLE_BGCOLOR
},
1384 { "TRIM_BGCOLOR", TRIM_BGCOLOR
},
1385 { "TRIM_SHADOW_COLOR", TRIM_SHADOW_COLOR
},
1386 { "MAINVIEW_PANES_COLOR", MAINVIEW_PANES_COLOR
},
1387 { "MAINVIEW_GRAPHICS_COLOR", MAINVIEW_GRAPHICS_COLOR
},
1388 { "HEADER_BGCOLOR", HEADER_BGCOLOR
},
1389 { "HEADER_ICON_BGCOLOR", HEADER_ICON_BGCOLOR
},
1390 { "HEADER_CURRENT_BGCOLOR", HEADER_CURRENT_BGCOLOR
},
1391 { "OVERLAY_COLOR", OVERLAY_COLOR
},
1392 { "MENU_HEADER_HEIGHT", MENU_HEADER_HEIGHT
},
1393 { "WHITE", (double)WHITE
},
1394 { "GREY", (double)GREY
},
1395 { "DARKGREY", (double)DARKGREY
},
1396 { "BLACK", (double)BLACK
},
1397 { "YELLOW", (double)YELLOW
},
1398 { "BLUE", (double)BLUE
},
1399 { "LIGHTGREY", (double)LIGHTGREY
},
1400 { "RED", (double)RED
},
1401 { "DARKRED", (double)DARKRED
},
1403 { "FIXEDWIDTH", FIXEDWIDTH
},
1405 #if defined(PCBHORUS)
1406 { "EVT_PAGEUP_FIRST", EVT_KEY_FIRST(KEY_PGUP
) },
1407 { "EVT_PAGEDN_FIRST", EVT_KEY_FIRST(KEY_PGDN
) },
1408 { "EVT_TELEM_FIRST", EVT_KEY_FIRST(KEY_TELEM
) },
1409 { "EVT_MODEL_FIRST", EVT_KEY_FIRST(KEY_MODEL
) },
1410 { "EVT_SYS_FIRST", EVT_KEY_FIRST(KEY_RADIO
) },
1411 { "EVT_RTN_FIRST", EVT_KEY_FIRST(KEY_EXIT
) },
1412 #elif defined(PCBXLITE)
1413 { "EVT_DOWN_FIRST", EVT_KEY_FIRST(KEY_DOWN
) },
1414 { "EVT_UP_FIRST", EVT_KEY_FIRST(KEY_UP
) },
1415 { "EVT_LEFT_FIRST", EVT_KEY_FIRST(KEY_LEFT
) },
1416 { "EVT_RIGHT_FIRST", EVT_KEY_FIRST(KEY_RIGHT
) },
1417 { "EVT_SHIFT_FIRST", EVT_KEY_FIRST(KEY_SHIFT
) },
1418 { "EVT_DOWN_BREAK", EVT_KEY_BREAK(KEY_DOWN
) },
1419 { "EVT_UP_BREAK", EVT_KEY_BREAK(KEY_UP
) },
1420 { "EVT_LEFT_BREAK", EVT_KEY_BREAK(KEY_LEFT
) },
1421 { "EVT_RIGHT_BREAK", EVT_KEY_BREAK(KEY_RIGHT
) },
1422 { "EVT_SHIFT_BREAK", EVT_KEY_BREAK(KEY_SHIFT
) },
1423 { "EVT_DOWN_LONG", EVT_KEY_LONG(KEY_DOWN
) },
1424 { "EVT_UP_LONG", EVT_KEY_LONG(KEY_UP
) },
1425 { "EVT_LEFT_LONG", EVT_KEY_LONG(KEY_LEFT
) },
1426 { "EVT_RIGHT_LONG", EVT_KEY_LONG(KEY_RIGHT
) },
1427 { "EVT_SHIFT_LONG", EVT_KEY_LONG(KEY_SHIFT
) },
1428 { "EVT_DOWN_REPT", EVT_KEY_REPT(KEY_DOWN
) },
1429 { "EVT_UP_REPT", EVT_KEY_REPT(KEY_UP
) },
1430 { "EVT_LEFT_REPT", EVT_KEY_REPT(KEY_LEFT
) },
1431 { "EVT_RIGHT_REPT", EVT_KEY_REPT(KEY_RIGHT
) },
1435 #elif defined(PCBTARANIS)
1436 { "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU
) },
1437 { "EVT_MENU_LONG", EVT_KEY_LONG(KEY_MENU
) },
1438 { "EVT_PAGE_BREAK", EVT_KEY_BREAK(KEY_PAGE
) },
1439 { "EVT_PAGE_LONG", EVT_KEY_LONG(KEY_PAGE
) },
1440 { "EVT_PLUS_BREAK", EVT_KEY_BREAK(KEY_PLUS
) },
1441 { "EVT_MINUS_BREAK", EVT_KEY_BREAK(KEY_MINUS
) },
1442 { "EVT_PLUS_FIRST", EVT_KEY_FIRST(KEY_PLUS
) },
1443 { "EVT_MINUS_FIRST", EVT_KEY_FIRST(KEY_MINUS
) },
1444 { "EVT_PLUS_REPT", EVT_KEY_REPT(KEY_PLUS
) },
1445 { "EVT_MINUS_REPT", EVT_KEY_REPT(KEY_MINUS
) },
1447 { "FILL_WHITE", FILL_WHITE
},
1448 { "GREY_DEFAULT", GREY_DEFAULT
},
1454 { "EVT_ENTER_BREAK", EVT_KEY_BREAK(KEY_ENTER
) },
1455 { "EVT_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER
) },
1456 { "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT
) },
1457 #if defined(ROTARY_ENCODER_NAVIGATION)
1458 { "EVT_ROT_BREAK", EVT_KEY_BREAK(KEY_ENTER
) },
1459 { "EVT_ROT_LONG", EVT_KEY_LONG(KEY_ENTER
) },
1460 { "EVT_ROT_LEFT", EVT_ROTARY_LEFT
},
1461 { "EVT_ROT_RIGHT", EVT_ROTARY_RIGHT
},
1464 { "DOTTED", DOTTED
},
1467 { "PLAY_NOW", PLAY_NOW
},
1468 { "PLAY_BACKGROUND", PLAY_BACKGROUND
},
1469 { "TIMEHOUR", TIMEHOUR
},
1471 #if defined(PCBHORUS)
1472 // Adding the unit consts for the set Telemetry function adds about 1k of flash usage
1473 {"UNIT_RAW", UNIT_RAW
},
1474 {"UNIT_VOLTS", UNIT_VOLTS
},
1475 {"UNIT_AMPS", UNIT_AMPS
},
1476 {"UNIT_MILLIAMPS", UNIT_MILLIAMPS
},
1477 {"UNIT_KTS", UNIT_KTS
},
1478 {"UNIT_METERS_PER_SECOND", UNIT_METERS_PER_SECOND
},
1479 {"UNIT_FEET_PER_SECOND", UNIT_FEET_PER_SECOND
},
1480 {"UNIT_KMH", UNIT_KMH
},
1481 {"UNIT_MPH", UNIT_MPH
},
1482 {"UNIT_METERS", UNIT_METERS
},
1483 {"UNIT_FEET", UNIT_FEET
},
1484 {"UNIT_CELSIUS", UNIT_CELSIUS
},
1485 {"UNIT_FAHRENHEIT", UNIT_FAHRENHEIT
},
1486 {"UNIT_PERCENT", UNIT_PERCENT
},
1487 {"UNIT_MAH", UNIT_MAH
},
1488 {"UNIT_WATTS", UNIT_WATTS
},
1489 {"UNIT_MILLIWATTS", UNIT_MILLIWATTS
},
1490 {"UNIT_DB", UNIT_DB
},
1491 {"UNIT_RPMS", UNIT_RPMS
},
1492 {"UNIT_G", UNIT_G
},
1493 {"UNIT_DEGREE", UNIT_DEGREE
},
1494 {"UNIT_RADIANS", UNIT_RADIANS
},
1495 {"UNIT_MILLILITERS", UNIT_MILLILITERS
},
1496 {"UNIT_FLOZ", UNIT_FLOZ
},
1497 {"UNIT_HOURS", UNIT_HOURS
},
1498 {"UNIT_MINUTES", UNIT_MINUTES
},
1499 {"UNIT_SECONDS", UNIT_SECONDS
},
1500 {"UNIT_CELLS", UNIT_CELLS
},
1501 {"UNIT_DATETIME", UNIT_DATETIME
},
1502 {"UNIT_GPS", UNIT_GPS
},
1503 {"UNIT_BITFIELD", UNIT_BITFIELD
},
1504 {"UNIT_TEXT", UNIT_TEXT
},
1506 { NULL
, 0 } /* sentinel */