forked from qba667/opentx
-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathlua-reference-guide.tex
340 lines (273 loc) · 11.5 KB
/
lua-reference-guide.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
\documentclass[a4paper,french,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage[T1]{fontenc}
\usepackage{geometry}
\usepackage{hyperref}
\usepackage{lmodern} % font Latin Modern, qui n'est pas une police Bitmap, donc tu auras de l'anti aliasing
\usepackage{tocloft}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{pifont,mdframed}
\usepackage{enumitem}
\usepackage[parfill]{parskip}
\usepackage{fancyhdr}
\usepackage{calc}
\usepackage{ifthen}
\setlength{\parskip}{\baselineskip}
\definecolor{luagray}{rgb}{0.96,0.96,0.96}
{\renewcommand{\arraystretch}{1.2} %<- modify value to suit your needs
%%%%%%%%%%%
% Defines the listings Lua style
%%%%%%%%%%%
\lstdefinestyle{myLuastyle}
{
language = {[5.0]Lua},
basicstyle = \ttfamily\footnotesize,
showstringspaces = false,
upquote = true,
frame = single,
captionpos = b,
breaklines =true,
backgroundcolor = \color{luagray},
}
%%%%%%%%%%
% Set the lua style as default listings style
%%%%%%%%%%
\lstset{style=myLuastyle}
%%%% On crée une figure Tikz qui permet de mettre le caractère passé en paramètre dans un rond (utilisé pour le symbole information
\newcommand\encircle[1]{%
\tikz[baseline=(X.base)]
\node (X) [draw, shape=circle, inner sep=0] {\strut #1};}
%%% Environnements
\newenvironment{warning}
{\par\begin{mdframed}[linewidth=2pt,linecolor=red]%
\begin{list}{}{\leftmargin=1cm
\labelwidth=\leftmargin}\item[\color{red}\Large\ding{53}]}
{\end{list}\end{mdframed}\par}
\newenvironment{info}
{\par\begin{mdframed}[linewidth=2pt,linecolor=blue]%
\begin{list}{}{\leftmargin=1cm
\labelwidth=\leftmargin}\item[\color{blue}\Large\ding{43}]}
{\end{list}\end{mdframed}\par}
\newenvironment{function}[1]
{\mdfsetup{
skipabove=\topsep,
skipbelow=\topsep,
innertopmargin=0pt,
innerbottommargin=4pt,
leftmargin=-13pt,
splitbottomskip=0ex,
splittopskip=0ex,
topline=false,
leftline=true,
bottomline=false,
rightline=false,
innerrightmargin=0pt,
innerlinewidth=2pt,
font=\normalfont,
frametitle={\textbf{local #1.}},
linecolor=black,
}
\begin{mdframed}%
}
{\end{mdframed}}
\geometry{top=2cm,bottom=2cm,left=2cm,right=1.5cm}
\pagestyle{fancy}
\renewcommand{\sectionmark}[1]{\markright{#1}}
\renewcommand{\footrulewidth}{1pt}
\fancyhf{}
\rhead{\fancyplain{}{Lua Scripting in OpenTx - Reference Guide }}
\lhead{\fancyplain{}{\rightmark }}
\rfoot{\fancyplain{}{\thepage}}
\lfoot{\fancyplain{}{Version 1.0}}
\title {
\vspace{60mm}
\Huge{\textsc{Lua Scripting in OpenTx\\}
\vspace{8mm}
\LARGE{\textsc{Reference Guide}}}
\vspace{45mm}
}
\author{OpenTx Team @ \url{http://www.open-tx.org/}}
\date{Version 1.0}
\begin{document}
\maketitle
\newpage
\tableofcontents
\newpage
\section{Introduction}
\paragraph{}
OpenTX 2.0 added support for Lua (current version 5.2.2) user scripts.
Lua is a lightweight multi-paradigm programming language designed as a scripting language\footnote{More at \href{http://www.wikipedia.org}{Wikipedia}}.
There are several types of Lua scripts used in openTX. More general information about Lua scripts can be found on page \url{http://www.open-tx.org/lua-instructions.html}
Lua scripts must be placed on SD card in correct folders and have an extension .lua. Maximum Lua script file name length is TODO characters. The script folders have been reorganized in OpenTX 2.0.3. The folder structure looks like this:
\begin{itemize}[leftmargin=*,itemsep=5mm,nolistsep]
\item[] \texttt{/SCRIPTS/WIZARD/} - For the Wizard script
\item[] \texttt{/SCRIPTS/MIXES/} - For model scripts
\item[] \texttt{/SCRIPTS/FUNCTIONS/} - For function scripts
\item[] \texttt{/SCRIPTS/<MODEL\_NAME>/telemXX.lua} - For telemetry scripts
\item[] \texttt{/SCRIPTS/TEMPLATES/} - For template scripts
\end{itemize}
\begin{figure}[h]
\begin{center}
\begin{longtable}{ll}
\toprule
\textbf{Lua Standard Libraries} & \textbf{Included} \\
\midrule
\endhead
\texttt{package} & no \\
\texttt{coroutine} & no \\
\texttt{table} & no \\
\texttt{io} & no \\
\texttt{os} & no \\
\texttt{string} & no \\
\texttt{bit} & future 2.1.0? \\
\texttt{math} & available from 2.0.0\\
\texttt{debug} & no \\
\bottomrule
\end{longtable}
\caption{Packaged libraries}
\end{center}
\end{figure}
\newpage
\section{Model Scripts}
\begin{warning}
Do not use Lua model scripts for controlling any aspect of your model that could cause a crash if script stops executing.
\end{warning}
\subsection{General description}
\paragraph{}
Each model can have several model scripts associated with it. These scripts are run periodically for entire time that model is selected/active. These scripts behave similar to standard OpenTX mixers but at the same time provide much more flexible and powerful tool.
Typically model scripts take several values as inputs, do some calculation or logic processing based on them and output one or more values. Each run of scripts should be as short as possible. Exceeding certain script execution runtime will result in script being forcefully stopped and disabled.
See also :
\begin{itemize}[leftmargin=*,itemsep=5mm,nolistsep]
\item[-] Lua \href{dunno}{One-time Scripts} - one-time running general scripts
\item[-] Lua \href{dunno}{Function Scripts}
\item[-] Lua \href{dunno}{Telemetry Scripts}
\item[-] Lua \href{dunno}{Script Reference} - detailed reference of OpenTX Lua implementation and interface
\item[-] Lua \href{dunno}{Script Examples} - some example scripts with comments
\end{itemize}
\subsubsection*{Examples of typical use of model scripts}
\begin{itemize}[leftmargin=*, itemsep=5mm,nolistsep]
\item[-] replacement for complex mixes that are \textbf{not critical to model function}
\item[-] complex processing of inputs and reaction to their current state and/or their history
\item[-] filtering of telemetry values
\item[-] automatic detection of number of battery cells and setting of low battery threshold
\item[-] automatic announcing of maximum altitude for each DLG throw
\item[-] see also Lua \href{dunno}{Script Examples}
\end{itemize}
\subsection{Limitations of model scripts}
\begin{itemize}[leftmargin=*,itemsep=5mm,nolistsep]
\item[-] Should not display anything on LCD screen.
\item[-] Can't wait for user input via dialog.
\item[-] Should not exceed maximum allowed runtime/ number of instructions.
\item[-] Standard OpenTX mixes are run every XX milliseconds in a very deterministic way (guaranteed execution) while model scripts are run from another thread with less priority. Their execution period is around 30ms and is not guaranteed!
\item[-] A script could be disabled/killed anytime due to several causes like (error in script, not enough free memory, etc...)
\end{itemize}
\subsection{Anatomy of model script}
\subsubsection{Location of model script}
\paragraph{}
Place them on SD card in folder \texttt{SCRIPTS/MIXES}
\subsubsection{Lifetime of model script}
\paragraph{}
\begin{itemize}[leftmargin=*,itemsep=5mm,nolistsep]
\item[-] script is loaded from SD card when model is selected
\item[-] script \textbf{init} function is called
\item[-] script \textbf{run} function is periodically called (inside GUI thread, period cca 30ms)
\item[-] script is stopped and disabled if it misbehaves (too long runtime, error in code, low memory)
\item[-] all model scripts are stopped while one-time script is running (see \href{dunno}{Lua One-time scripts})
\end{itemize}
\subsubsection{Script interface definitionn}
\paragraph{}
Every script must include a \textbf{return} statement at the end, that defines its interface to the rest of OpenTX code.
This statement defines:
\begin{itemize}[leftmargin=*,itemsep=5mm,nolistsep]
\item[-] script \textbf{inputs} (optional)
\item[-] script \textbf{outputs} (optional)
\item[-] script \textbf{init} function (optional)
\item[-] script \textbf{run} function
\end{itemize}
For example:
\begin{lstlisting}[caption={A dummy Lua script}]
-- script body would be here
return { input=inputs, output=outputs, run=run_func, init=init_func }
\end{lstlisting}
This example defines :
\begin{itemize}[leftmargin=*,itemsep=5mm,nolistsep]
\item[-] \texttt{inputs} table (array) as \textbf{input} values to model script
\item[-] \texttt{outputs} table as \textbf{output} of model script
\item[-] \texttt{run\_func()} as \textbf{periodic execution function} that takes inputs as parameters and returns outputs table
\item[-] \texttt{init\_func()} as function that is \textbf{called one time} when script is loaded and begins execution.
\end{itemize}
\paragraph{}
\begin{info}
Parameters \textbf{init}, \textbf{input} and \textbf{output} are optional. \\ If model script doesn't use them, they can be omitted from return statement.
\end{info}
\begin{lstlisting}[caption={Example without init and output}]
local inputs = { { "Aileron", SOURCE }, { "Ail. ratio", VALUE, -100, 100, 0 } }
local function run_func(ail, ratio)
-- do some stuff
if (ail > 50) and ( ratio < 40) then
playFile("foo.wav")
end
end
-- script that only uses input and run
return { run=run_func, input=inputs }
\end{lstlisting}
\newpage
\subsubsection{Script interface definition}
\paragraph{}
If defined, \textbf{init} function is called right after the script is loaded from SD card and begins execution. Init is called \textbf{only once} before the run function is called for the first time.
\begin{longtable}{p{3cm}p{3cm}p{\dimexpr\columnwidth-6cm-6\tabcolsep\relax}}
\toprule
\textbf{Prototype} & \multicolumn{2}{l} {\texttt{local <init\_function\_name>()}} \\
\midrule
\textbf{Parameters} & none & \\
\midrule
\textbf{Returns} & none & \\
\bottomrule
\end{longtable}
\subsubsection{Script execution}
\paragraph{}
The \textbf{run} function is the function that is periodically called for the entire lifetime of script. Syntax of run function is different between model scripts and one-time scripts.
\begin{longtable}{p{3cm}p{3cm}p{\dimexpr\columnwidth-6cm-6\tabcolsep\relax}}
\toprule
\textbf{Prototype} & \multicolumn{2}{l} {\texttt{local <run\_function\_name>([first input, [second input], ...])}} \\
\midrule
\textbf{Parameters} & <> & zero or more input values, their names are arbitrary, their meaning and order is defined by the input table \\
\midrule
\textbf{Returns} & none & if output table is empty (i.e. script has no output) \\
& values & (comma separated list of values) list of output values, their order and meaning is defined by the output table \\
\bottomrule
\end{longtable}
\subsubsection{Macro Test}
\newcounter{parameters}
\newcounter{returns}
\newenvironment{funcdef}[0]
{\setcounter{parameters}{0}\setcounter{returns}{0}
\newcommand{\prototype}[1]{\textbf{Prototype} & \multicolumn{2}{l} {\texttt{##1}}}
\newcommand{\parameter}[2]{\ifthenelse{\value{parameters}=0}{\\\midrule\textbf{Parameters}}{\\}\stepcounter{parameters}& \texttt{##1} & ##2}
\newcommand{\return}[2]{\ifthenelse{\value{returns}=0}{\\\midrule\textbf{Returns}}{\\}\stepcounter{returns}& ##1 & ##2}
\begin{longtable}{p{3cm}p{3cm}p{\dimexpr\columnwidth-6cm-6\tabcolsep\relax}}
\toprule}
{\\\bottomrule
\end{longtable}}
\begin{funcdef}
\prototype{local <run\_function\_name>([first input, [second input], ...])}
\parameter{<>}{zero or more input values, their names are arbitrary, their meaning and order is defined by the input table}
\parameter{none}{test}
\parameter{none}{test}
\return{none}{[text...]}
\return{none}{[text...]}
\return{none}{[text...]}
\return{none}
\end{funcdef}
\begin{funcdef}
\prototype{playNumber(number, unit, att)}
\parameter{number}{(integer)}
\parameter{unit}{(integer)}
\parameter{att}{(integer)}
\return{nil}
\end{funcdef}
\end{document}