/* * Authors (alphabetical order) * - Andre Bernet * - Andreas Weitl * - Bertrand Songis * - Bryan J. Rentoul (Gruvin) * - Cameron Weeks * - Erez Raviv * - Gabriel Birkus * - Jean-Pierre Parisy * - Karl Szmutny * - Michael Blandford * - Michal Hlavinka * - Pat Mackenzie * - Philip Moss * - Rob Thomson * - Romolo Manfredini * - Thomas Husterer * * opentx is based on code named * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, * er9x by Erez Raviv: http://code.google.com/p/er9x/, * and the original (and ongoing) project by * Thomas Husterer, th9x: http://code.google.com/p/th9x/ * * 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 #include #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) #include "lua/lua_exports_taranis.inc" #endif #if defined(PCBTARANIS) && defined(REV9E) #define RADIO "taranisx9e" #elif defined(PCBTARANIS) && defined(REVPLUS) #define RADIO "taranisplus" #elif defined(PCBTARANIS) #define RADIO "taranis" #elif defined(PCBHORUS) #define RADIO "horus" #elif defined(PCBFLAMENCO) #define RADIO "flamenco" #error "Unknown board" #endif #if defined(SIMU) #define RADIO_VERSION RADIO"-simu" #else #define RADIO_VERSION RADIO #endif #define FIND_FIELD_DESC 0x01 struct LuaField { uint16_t id; char desc[50]; }; /*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 */ { uint32_t gpsLat = 0; uint32_t gpsLon = 0; telemetryItem.gps.extractLatitudeLongitude(&gpsLat, &gpsLon); /* close, but not the format we want */ lua_createtable(L, 0, 4); lua_pushtablenumber(L, "lat", gpsLat / ((telemetryItem.gps.latitudeNS == 'S') ? -1000000.0 : 1000000.0)); lua_pushtablenumber(L, "pilot-lat", telemetryItem.pilotLatitude / ((telemetryItem.gps.latitudeNS == 'S') ? -1000000.0 : 1000000.0)); lua_pushtablenumber(L, "lon", gpsLon / ((telemetryItem.gps.longitudeEW == 'W') ? -1000000.0 : 1000000.0)); lua_pushtablenumber(L, "pilot-lon", telemetryItem.pilotLongitude / ((telemetryItem.gps.longitudeEW == 'W') ? -1000000.0 : 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=0) { // TODO better search method (binary lookup) for (unsigned int n=0; n