\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}

