Skip to content

2.1 Level I : Your Very First Widget

Udo edited this page Nov 20, 2024 · 8 revisions

1. The "Basic Framework"

The introductory chapter already covered the topics of folders and handlers.

To make the widget (or, more generally, the script) functional, a script file must be "visible" to the transmitter and must define the necessary handlers (even if they're empty initially).

I always use a template file for this, where only the widget name and the key, i.e., the unique script identifier, need to be adjusted.

I am providing an example of such a template file.
It is located in the "Template01" folder as the file main.lua.
The template defines a widget with the basic handlers:

  • create
  • wakeup
  • paint
  • configure
  • event



Instructions

  1. Create a Folder
    In the very first step, create a folder (e.g., tutorial2.1) under the /scripts directory and copy the file there.

  2. Adjust the Template
    Next, open the file in an editor and adjust the name and key.

    You can set the name and key as you like, with the following conditions:

    • The name should not exceed approximately 30 characters.
      (This is not a strict limit, but exceeding it may cause display problems.)
    • The key must not exceed a length of 7 characters.
  3. Check Functionality
    After making these adjustments, I recommend checking if the widget is functional.

    To do this, restart the simulator or transmitter, and in an empty widget frame, you should now be able to configure a widget with the name you just set.





2. Displaying Text

Of course, you could simply call the relevant method with its parameters to show how something can be "output" in the widget.

However, it's more important to demonstrate how to find this information if you're unsure, allowing you to develop solutions on your own.

How to Get Information: The Lua Reference Guide

The official Lua Reference Guide serves as the primary source of information.
To get started, navigate to the class overview.
A class is essentially a container for functions (or more precisely, methods) that serve similar tasks.

Lua Reference Guide – Class Overview




Initially, you may not have a strong sense of which class is suited to which "task," but as you gain practical experience, this understanding will develop quickly.





The "lcd" Class for Anything Displayed on the Screen

For "our task"—displaying text on the screen—the lcd class is responsible.
When we look into the lcd class, we see the available methods, and we quickly find the method lcd.drawText().
Documentation: lcd.drawText()

With all parameters, the correct syntax would be:

lcd.drawText(x, y, "Display text", TEXT_LEFT)



Coordinates in the Widget

Pay special attention here:
In the method, coordinates are specified for positioning the text.
These are NOT the coordinates on the display!

These coordinates in the code always refer to the area within the widget itself.
The widget is essentially its own world, and the code cannot break out of it. This applies in many other contexts as well.

Since users can choose different screen layouts with different frame sizes, the programmer may need to query and account for these sizes in the code.
The X18 and X20 series also have different screen resolutions, which can further influence the overall layout.

For now, we’ll keep it simple and ignore this complexity.
In the code, I’ll declare two variables that will provide different values based on the transmitter type to achieve approximately suitable placement.



Keep an Eye on the Reference Guide

Why TEXT_LEFT for alignment and not LEFT as described in the guide?

These are the little things that sometimes happen.
In this case, during the development of Ethos Lua, the constant LEFT was standardized to TEXT_LEFT, but the guide hasn’t been updated to reflect this.

So, here’s a quick detour into system constants:


System Constants

When you start working more with Ethos Lua and apply more and more different methods, you'll encounter numerous constants that are used as parameters.
For example, in the method description for lcd.drawText():
As of September 2024, "LEFT," "RIGHT," or "CENTERED" can be specified as optional fourth parameters.


What’s behind constants in general?

Ultimately, in Lua, a constant is an unchangeable number, text, or table value, which, unfortunately, isn't "self-explanatory."
Does everyone immediately know that the table {238,130,238} corresponds to the RGB value for violet, for example?
Therefore, certain values are often converted into names/labels to make them easier to read in the code.

In Lua, a constant is declared in the code like this:

local PI <const> = 3.141

to assign the constant PI the floating-point value 3.141.

In the "violet" example, we go a step further and declare the constant directly as an Ethos RGB color value using the method lcd.RGB:

local VIOLET <const> = lcd.RGB(238,130,238)

So, what does all this have to do with the "LEFT" issue mentioned above? Quite simply:

All system constants are listed in the Reference Guide under "base": https://www.frsky-rc.com/wp-content/uploads/Downloads/EthosSuite/LuaDoc/classbase.html

For the system constant "LEFT," you’ll find the unassuming entry: "LEFT Text alignment (deprecated)." And "deprecated" means that it’s an outdated constant that may soon no longer be supported.

So, you look for the corresponding new constant under "base" and come across "TEXT_LEFT."

By the way, for those who haven’t done much programming yet:

CONSTANTS are always written in uppercase in the code for better readability (-;

Now, back to our little widget. After all, we just wanted to display two lines of text.



Choosing a Color

To spruce things up a bit, we want to display each line in a different color.
If you're unsure how to do this, check the Reference Guide and look at the lcd class. You’ll find lcd.color().

image

The color selection function is straightforward; as soon as the method is called, all subsequent outputs (text, numbers, drawing shapes and lines, etc.) will be in the corresponding color until the next color is selected.



Font Size

If you want, you can also experiment with font sizes. By now, we know the process (I’ll refer to the Reference Guide for the last time >> lcd class) and find the method lcd.font().

In the base description "base," which lists the constants, you can see that sizes like:

  • FONT_S
  • FONT_STD
  • FONT_XL

and several others exist as parameters for lcd.font().

In the example code, I’ve pre-defined a few sizes for experimentation.
The size itself depends on the display type (X18 / X20 / Horus series), as we'll soon see.




3. The main Code

We have now learned about the three methods lcd.drawText, lcd.font(), and lcd.color(), and we understand a bit about working with constants.

Altogether, I'll now combine these into a small code snippet in a logical sequence:

	local offset 	= 2
	local line 	= 46		-- x20
--	local line 	= 27		-- x18
--	local line 	= 24		-- x10

	lcd.font(FONT_XXL)
--	lcd.font(FONT_XL)		-- X10

	lcd.color(COLOR_RED)
	lcd.drawText(50,offset +line*0,"hello 1",TEXT_LEFT)

	lcd.color(COLOR_GREEN)
	lcd.drawText(50,offset +line*1,"hello 2",TEXT_LEFT)

You can see that:

  • I define two variables, offset and line (line height in points), which will later be used in calculating the y-positioning of the text.
  • The font size is set.
  • Then, a color is selected, and text is displayed.

The widget is now (almost) complete; Lua isn't rocket science! ;-)


Note:

I’m also using the option to add comments here.
All lines or sections that start with two consecutive hyphens -- are ignored by Lua.
This allows the user to easily experiment with different font sizes or make slight positioning adjustments based on the display type.

The script works without modification on the X20.
For the X10/X18, you need to activate the corresponding lines and comment out the X20 lines.
Just give it a try.

The main purpose of commenting is to add explanations (such as which values are suitable for which display type, X18 or X20), but it’s also a quick and simple way to test various things when you’re getting started.


4. A Matter of Handlers

Now we’ve assembled the core code.
The task was relatively simple, focusing on displaying text with a few "refinements."
For beginners, a question might arise as to where this code snippet fits within the overall structure.

The different handlers were introduced in the first chapter, and if you review that, it’s pretty clear that our "code snippet" belongs to the paint handler.

After all, the paint handler is responsible for all types of display and "control" of the screen.

The Fundamental Rule should be:

The two main modules/handlers of a typical widget are paint and wakeup.

  • Paint should contain only the coding necessary for output to maintain efficiency.
  • Everything else (calculations, querying values like telemetry or switch positions, etc.) should be done in wakeup.
  • The paint handler should be called as infrequently as possible.



To make the widget functional, you only need to copy the code snippet into the paint handler section of the Lua template mentioned before.
The "ready to start" version can be found in the folder tut 2.1.

I assume that, as a beginner, you’ll use the simulator for effective learning.
The template has already been tested previously.

Once the code is inserted, you can press the F12 key in the simulator, and the changes should be applied.
If you’ve configured a small widget accordingly, the final result will look like this:

image

Congratulations, your first widget is complete!

Clone this wiki locally