LUA Reference Guide
2.9
2.9
  • EdgeTX 2.9 Lua Reference Guide
  • Introduction
    • Acknowledgments
    • Getting Started
  • Script Type Overview
    • Custom (Mixer) Scripts
    • Telemetry Scripts
    • One-Time Scripts
    • Function Scripts
    • Widget Scripts
  • EdgeTX Lua API Programming Guide
    • Lua Basics
    • Loading Code Modules Dynamically
    • Saving Memory
    • Using Key and Touch Events
    • Drawing Flags and Colors
    • Data Exchange with the EdgeTX Model Setup
    • Included Lua Libraries
      • io Library
        • io.open()
        • io.close()
        • io.read()
        • io.write()
        • io.seek()
  • EdgeTX Lua API Reference
    • Constants
      • Key Event Constants
      • Touch Event Constants
      • Flags and Pattern Constants
      • Color Constants
      • Special Character Constants
      • Screen Constants
      • Logical Switch Function Constants
      • Special Function Constants
      • Widget Options Constants
    • General Functions
      • GREY()
      • accessTelemetryPush()
      • chdir(directory)
      • crossfireTelemetryPop()
      • crossfireTelemetryPush()
      • defaultChannel(stick)
      • defaultStick(channel)
      • flushAudio()
      • getAvailableMemory()
      • getDateTime()
      • getFieldInfo(source)
      • getFlightMode(mode)
      • getGeneralSettings()
      • getGlobalTimer()
      • getLogicalSwitchValue(id)
      • getOutputValue(outputIndex)
      • getRAS()
      • getRSSI()
      • getRotEncMode()
      • getRotEncSpeed()
      • getRtcTime()
      • getShmVar(id)
      • getSourceIndex(sourceName)
      • getSourceName(sourceIndex)
      • getSourceValue(source)
      • getSwitchIndex(positionName)
      • getSwitchName(switchIndex)
      • getSwitchValue(switchIndex)
      • getTime()
      • getTxGPS()
      • getUsage()
      • getValue(source)
      • getVersion()
      • ghostTelemetryPop()
      • ghostTelemetryPush()
      • killEvents(key)
      • loadScript(file [, mode], [,env])
      • multiBuffer(address[,value])
      • playDuration(duration [, hourFormat])
      • playFile(name)
      • playHaptic(duration, pause [, flags])
      • playNumber(value, unit [, attributes])
      • playTone(frequency, duration, pause [, flags [, freqIncr]])
      • popupConfirmation(title, message, event)
      • popupInput(title, event, input, min, max)
      • popupWarning(title, event)
      • resetGlobalTimer([type])
      • serialGetPower(port_nr)
      • serialRead([num])
      • serialSetPower(port_nr, value)
      • serialWrite(str)
      • setSerialBaudrate(baudrate)
      • setShmVar(id, value)
      • setStickySwitch(id, value)
      • setTelemetryValue(id, subID, instance, value [, unit [, precision [, name]]])
      • sources([first[, last]])
      • switches([first[, last]])
      • sportTelemetryPop()
      • sportTelemetryPush()
    • Model Functions
      • model.defaultInputs()
      • model.deleteFlightModes()
      • model.deleteInput(input, line)
      • model.deleteInputs()
      • model.deleteMix(channel, line)
      • model.deleteMixes()
      • model.getCurve(curve)
      • model.getCustomFunction(function)
      • model.getFlightMode(index)
      • model.getGlobalVariable(index, flight_mode)
      • model.getInfo()
      • model.getInput(input, line)
      • model.getInputsCount(input)
      • model.getLogicalSwitch(switch)
      • model.getMix(channel, line)
      • model.getMixesCount(channel)
      • model.getModule(index)
      • model.getOutput(index)
      • model.getSensor(sensor)
      • model.getSwashRing()
      • model.getTimer(timer)
      • model.insertInput(input, line, value)
      • model.insertMix(channel, line, value)
      • model.resetSensor(sensor)
      • model.resetTimer(timer)
      • model.setCurve(curve, params)
      • model.setCustomFunction(function, value)
      • model.setFlightMode(index, params)
      • model.setGlobalVariable(index, flight_mode, value)
      • model.setInfo(value)
      • model.setLogicalSwitch(switch, value)
      • model.setModule(index, value)
      • model.setOutput(index, value)
      • model.setSwashRing(params)
      • model.setTimer(timer, value)
    • Lcd Functions
      • Lcd Functions Overview
      • lcd.RGB(r, g, b | rgb)
      • lcd.clear([color])
      • lcd.drawAnnulus(x, y, r1, r2, start, end [, flags])
      • lcd.drawArc(x, y, r, start, end [, flags])
      • lcd.drawBitmap(bitmap, x, y [, scale])
      • lcd.drawBitmapPattern(bitmap, x, y [, flags])
      • lcd.drawBitmapPatternPie(bitmap, x, y, startAngle, endAngle [, flags])
      • lcd.drawChannel(x, y, source, flags)
      • lcd.drawCircle(x, y, r [, flags])
      • lcd.drawCombobox(x, y, w, list, idx [, flags])
      • lcd.drawFilledCircle(x, y, r [, flags])
      • lcd.drawFilledRectangle(x, y, w, h [, flags])
      • lcd.drawFilledTriangle(x1, y1, x2, y2, x3, y3 [, flags])
      • lcd.drawGauge(x, y, w, h, fill, maxfill [, flags])
      • lcd.drawHudRectangle(pitch, roll, xmin, xmax, ymin, ymax [, flags])
      • lcd.drawLine(x1, y1, x2, y2, pattern, flags)
      • lcd.drawLineWithClipping(x1, y1, x2, y2, xmin, xmax, ymin, ymax, pattern [, flags])
      • lcd.drawNumber(x, y, value [, flags [, inversColor]])
      • lcd.drawPie(x, y, r, start, end [, flags])
      • lcd.drawPixmap(x, y, name)
      • lcd.drawPoint(x, y)
      • lcd.drawRectangle(x, y, w, h [, flags [, t]])
      • lcd.drawScreenTitle(title, page, pages)
      • lcd.drawSource(x, y, source [, flags])
      • lcd.drawSwitch(x, y, switch, flags)
      • lcd.drawText(x, y, text [, flags [, inversColor]])
      • lcd.drawTextLines(x, y, w, h, text [, flags])
      • lcd.drawTimer(x, y, value [, flags [, inversColor]])
      • lcd.drawTriangle(x1, y1, x2, y2, x3, y3 [, flags])
      • lcd.exitFullScreen()
      • lcd.getColor(flags)
      • lcd.getLastLeftPos()
      • lcd.getLastPos()
      • lcd.getLastRightPos()
      • lcd.invertRect(x, y, w, h [, flags])
      • lcd.refresh()
      • lcd.resetBacklightTimeout()
      • lcd.setColor(colorIndex, color)
      • lcd.sizeText(text [, flags])
    • Bitmap Functions
      • Bitmap.getSize(name)
      • Bitmap.open(name)
      • Bitmap.resize(bitmap, width, height)
      • Bitmap.toMask(bitmap)
    • Filesystem
      • dir(directory)
      • fstat(path)
      • del(file or directory)
  • Advanced Topics
    • Lua data sharing across scripts
    • Debugging techniques
    • Speed/memory optimizaton tricks
  • Appendix
    • Fonts
    • Units
Powered by GitBook
On this page
  • Introduction
  • First Class Functions
  • Closures
  • Functions with Variable Number of Arguments
  • References

Was this helpful?

Export as PDF
  1. EdgeTX Lua API Programming Guide

Lua Basics

Lua is a small but powerful language. This section will explain a few of the most important concepts.

PreviousEdgeTX Lua API Programming GuideNextLoading Code Modules Dynamically

Last updated 2 years ago

Was this helpful?

Introduction

Lua was chosen for OpenTX, and hence also EdgeTX, because it is a small language designed to be highly extensible by libraries written in C and C++, so it can be integrated into other systems like EdgeTX. It is also relatively efficient, both in terms of memory and CPU usage, and hence well suited for the radios.

In addition to the provided libraries, Lua has a very elegant mechanism for loading new Lua code modules during run-time. A lot of the elegance comes from the way that the loading mechanism meshes with another concept supported by Lua: first class functions with closures.

First Class Functions

Computer science pioneer Christopher Strachey introduced the concept of functions as first-class objects in his paper from 1967. What it means is that functions can be treated as other variables: as arguments passed in function calls, as results returned from function calls, and a function identifier can be re-assigned to another chunk of function code, just like a variable ca be assigned to a new value.

In Lua, a function declaration is really "syntactic sugar" for assigning a variable to the chunk of code that is called when the function is invoked, i.e.

local function f(x) return x + 1 end

is the same as

local f = function(x) return x + 1 end

You can even add functions to Lua tables, i.e.

t = { f = f }

will add the above function to the table t, as a field that is also called f. Does that look familiar to the return statement required at the end of a Lua script?

Yes indeed, because a script is really an anonymous function that returns a list of functions to the system. The function declarations assign variables to chunks of function code, these variables are added to the list returned at the end of the script, and the system then calls the functions periodically to run the script. So the script itself is run one time initially, and subsequently the functions returned by the last statement are called periodically.

Closures

Another important concept that goes with first-class functions, is closures. This is the environment of the function with the variable names that the function can see. Please consider the following function counter that returns another function:

local function counter(start, step)
  local x = start

  return function()
    local y = x
    x = x + step
    return y
  end
end

The function is returned directly without being assigned to a variable name. The closure of the function returned is the body of the function counter, containing both the arguments start and step, and the local variable x. So if c1 = counter(1, 1) then c1() will return 1, 2, 3, ... when called repeatedly, and if c2 = counter(2, 3) then c2() will return 2, 5, 8, ...

Likewise, the local variables that you declare outside the functions of your script can be used by all of the functions in your script, and they persist between function calls, but they are not visible to other scripts.

Functions with Variable Number of Arguments

Please consider this function:

local function match(x, ...)
  for i, y in ipairs({...}) do
    if x == y then
      return true
    end
  end
  return false
end

if event == EVT_VIRTUAL_ENTER or event == EVT_VIRTUAL_EXIT then

can be replaced by

if match(event, EVT_VIRTUAL_ENTER, EVT_VIRTUAL_EXIT) then

You can also use ... directly as a comma separated list of values, e.g. local a, b, c = ... will assign the three variables to the three first arguments following x, or nil if none are given.

References

The are a little trickier, as you can register multiple instances of the same widget script, and all of these instances run within the same Lua closure. Therefore, local variables declared outside any functions in a widget script are shared among all of the instances of that script. But each call to the create(...) function returns a new widget list to the system. And since this list is unique to each instance, you can add private instance variables to it.

It takes an argument x and a list ... A vararg list is just like a list of arguments separated by commas, and you can call the function with any number of arguments greater than 1. Inside the function, you can also treat ... like a comma separated list of variables, e.g. in the above function, ... is converted to a table by {...} just like you could construct a table by e.g. {a, b, c}. The table is iterated with the ipairs function to look for an element matching the first argument x. So e.g. the following statement

The helpful, both if you want to learn more about Lua, and if you want to search for answers to specific questions.

Fundamental Concepts in Programming Languages
widget scripts
vararg
Lua 5.2 Reference Manual