1 ---- #########################################################################
3 ---- # Copyright (C) OpenTX #
5 ---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
7 ---- # This program is free software; you can redistribute it and/or modify #
8 ---- # it under the terms of the GNU General Public License version 2 as #
9 ---- # published by the Free Software Foundation. #
11 ---- # This program is distributed in the hope that it will be useful #
12 ---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 ---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 ---- # GNU General Public License for more details. #
16 ---- #########################################################################
19 local ELEVONS_PAGE
= 1
21 local CONFIRMATION_PAGE
= 3
23 -- Navigation variables
24 local page
= ENGINE_PAGE
42 local function blinkChanged()
43 local time
= getTime() % 128
44 local blink
= (time
- time
% 64) / 64
45 if blink
~= lastBlink
then
53 local function fieldIncDec(event
, value
, max, force
)
54 if edit
or force
==true then
55 if event
== EVT_PLUS_BREAK
or event
== EVT_ROT_LEFT
then
58 elseif event
== EVT_MINUS_BREAK
or event
== EVT_ROT_RIGHT
then
59 value
= (value
+ max + 2)
62 value
= (value
% (max+1))
67 local function valueIncDec(event
, value
, min, max)
69 if event
== EVT_PLUS_FIRST
or event
== EVT_PLUS_REPT
or event
== EVT_ROT_RIGHT
then
74 elseif event
== EVT_MINUS_FIRST
or event
== EVT_MINUS_REPT
or event
== EVT_ROT_LEFT
then
84 local function navigate(event
, fieldMax
, prevPage
, nextPage
)
85 if event
== EVT_ENTER_BREAK
then
89 if event
== EVT_EXIT_BREAK
then
93 dirty
= blinkChanged()
96 if event
== EVT_PAGE_BREAK
then
100 elseif event
== EVT_PAGE_LONG
then
106 field
= fieldIncDec(event
, field
, fieldMax
, true)
111 local function getFieldFlags(position
)
113 if field
== position
then
116 flags
= INVERS
+ BLINK
122 local function channelIncDec(event
, value
)
123 if not edit
and event
==EVT_MENU_BREAK
then
127 value
= valueIncDec(event
, value
, 0, 15)
133 local function init()
134 rudCH1
= defaultChannel(0)
135 thrCH1
= defaultChannel(2)
136 elevCH1
= defaultChannel(1)
137 elevCH2
= defaultChannel(3)
141 local engineModeItems
= {"No", "Yes..."}
142 local function drawEngineMenu()
144 lcd
.drawText(1, 0, "Has your model got an engine?", 0)
145 lcd
.drawFilledRectangle(0, 0, LCD_W
, 8, GREY_DEFAULT
+FILL_WHITE
)
146 lcd
.drawCombobox(0, 8, LCD_W
/2, engineModeItems
, engineMode
, getFieldFlags(0))
147 lcd
.drawLine(LCD_W
/2-1, 18, LCD_W
/2-1, LCD_H
-1, DOTTED
, 0)
148 if engineMode
== 0 then
150 lcd
.drawPixmap(132, 8, "engine-0.bmp")
154 lcd
.drawPixmap(132, 8, "engine-1.bmp")
155 lcd
.drawText(25, LCD_H
-16, "Assign channel", 0);
156 lcd
.drawText(LCD_W
/2-19, LCD_H
-8, ">>>", 0);
157 lcd
.drawSource(151, LCD_H
-8, MIXSRC_CH1
+thrCH1
, getFieldFlags(1))
162 local function engineMenu(event
)
168 navigate(event
, fieldsMax
, page
, page
+1)
171 engineMode
= fieldIncDec(event
, engineMode
, 1)
173 thrCH1
= channelIncDec(event
, thrCH1
)
178 local elevonsModeItems
= {"2 Channels..."}
179 local function drawElevonsMenu()
181 lcd
.drawText(1, 0, "Select elevon channnels", 0)
182 lcd
.drawFilledRectangle(0, 0, LCD_W
, 8, GREY_DEFAULT
+FILL_WHITE
)
183 lcd
.drawCombobox(0, 8, LCD_W
/2, elevonsModeItems
, elevonsMode
, 0)
184 lcd
.drawLine(LCD_W
/2-1, 18, LCD_W
/2-1, LCD_H
-1, DOTTED
, 0)
185 lcd
.drawPixmap(110, 9, "elevons.bmp")
186 lcd
.drawText(20, LCD_H
-16, "Assign channels", 0);
187 lcd
.drawText(LCD_W
/2-19, LCD_H
-8, ">>>", 0);
188 lcd
.drawSource(116, LCD_H
-8, MIXSRC_CH1
+elevCH1
, getFieldFlags(0))
189 lcd
.drawSource(175, LCD_H
-8, MIXSRC_CH1
+elevCH2
, getFieldFlags(1))
193 local function elevonsMenu(event
)
199 navigate(event
, fieldsMax
, page
-1, page
+1)
202 elevCH1
= channelIncDec(event
, elevCH1
)
204 elevCH2
= channelIncDec(event
, elevCH2
)
209 local rudderModeItems
= {"No", "Yes..."}
211 local function drawRudderMenu()
213 lcd
.drawText(1, 0, "Has your model got a rudder?", 0)
214 lcd
.drawFilledRectangle(0, 0, LCD_W
, 8, GREY_DEFAULT
+FILL_WHITE
)
215 lcd
.drawCombobox(0, 8, LCD_W
/2, rudderModeItems
, rudderMode
, getFieldFlags(0))
216 lcd
.drawLine(LCD_W
/2-1, 18, LCD_W
/2-1, LCD_H
-1, DOTTED
, 0)
217 if rudderMode
== 0 then
219 lcd
.drawPixmap(109, 14, "drudder-0.bmp")
223 lcd
.drawPixmap(109, 14, "drudder-1.bmp")
224 lcd
.drawText(25, LCD_H
-16, "Assign channel", 0);
225 lcd
.drawText(LCD_W
/2-19, LCD_H
-8, ">>>", 0);
226 lcd
.drawSource(190, LCD_H
-55, MIXSRC_CH1
+rudCH1
, getFieldFlags(1))
231 local function rudderMenu(event
)
237 navigate(event
, fieldsMax
, page
-1, page
+1)
240 rudderMode
= fieldIncDec(event
, rudderMode
, 1)
242 rudCH1
= channelIncDec(event
, rudCH1
)
246 -- Servo (limits) Menu
247 local function drawServoMenu(limits
)
249 lcd
.drawSource(1, 0, MIXSRC_CH1
+servoPage
, 0)
250 lcd
.drawText(25, 0, "servo min/max/center/direction?", 0)
251 lcd
.drawFilledRectangle(0, 0, LCD_W
, 8, GREY_DEFAULT
+FILL_WHITE
)
252 lcd
.drawLine(LCD_W
/2-1, 8, LCD_W
/2-1, LCD_H
-1, DOTTED
, 0)
253 lcd
.drawText(LCD_W
/2-19, LCD_H
-8, ">>>", 0);
254 lcd
.drawPixmap(122, 8, "servo.bmp")
255 lcd
.drawNumber(140, 35, limits
.min, PREC1
+getFieldFlags(0));
256 lcd
.drawNumber(205, 35, limits
.max, PREC1
+getFieldFlags(1));
257 lcd
.drawNumber(170, 9, limits
.offset
, PREC1
+getFieldFlags(2));
258 if limits
.revert
== 0 then
259 lcd
.drawText(129, 50, "\126", getFieldFlags(3));
261 lcd
.drawText(129, 50, "\127", getFieldFlags(3));
266 local function servoMenu(event
)
267 local limits
= model
.getOutput(servoPage
)
271 drawServoMenu(limits
)
274 navigate(event
, fieldsMax
, page
, page
)
278 limits
.min = valueIncDec(event
, limits
.min, -1000, 0)
280 limits
.max = valueIncDec(event
, limits
.max, 0, 1000)
282 limits
.offset
= valueIncDec(event
, limits
.offset
, -1000, 1000)
284 limits
.revert
= fieldIncDec(event
, limits
.revert
, 1)
286 model
.setOutput(servoPage
, limits
)
287 elseif event
== EVT_EXIT_BREAK
then
294 local function addMix(channel
, input
, name
, weight
, index
)
295 local mix
= { source
=input
, name
=name
}
296 if weight
~= nil then
302 model
.insertMix(channel
, index
, mix
)
305 local function applySettings()
306 model
.defaultInputs()
308 if engineMode
== 1 then
309 addMix(thrCH1
, MIXSRC_FIRST_INPUT
+defaultChannel(2), "Engine")
311 addMix(elevCH1
, MIXSRC_FIRST_INPUT
+defaultChannel(1), "Elev1-E", 50)
312 addMix(elevCH1
, MIXSRC_FIRST_INPUT
+defaultChannel(3), "Elev1-A", 50, 1)
313 addMix(elevCH2
, MIXSRC_FIRST_INPUT
+defaultChannel(1), "Elev2-E", 50)
314 addMix(elevCH2
, MIXSRC_FIRST_INPUT
+defaultChannel(3), "Elev2-A", -50, 1)
315 if rudderMode
== 1 then
316 addMix(rudCH1
, MIXSRC_FIRST_INPUT
+defaultChannel(0), "Rudder")
320 local function drawNextLine(x
, y
, label
, channel
)
321 lcd
.drawText(x
, y
, label
, 0);
322 lcd
.drawSource(x
+52, y
, MIXSRC_CH1
+channel
, 0)
331 local function drawConfirmationMenu()
335 lcd
.drawText(48, 1, "Ready to go?", 0);
336 lcd
.drawFilledRectangle(0, 0, LCD_W
, 9, 0)
337 if engineMode
== 1 then
338 x
, y
= drawNextLine(x
, y
, "Throttle:", thrCH1
)
340 x
, y
= drawNextLine(x
, y
, "Elevons:", elevCH1
)
341 x
, y
= drawNextLine(x
, y
, "Elevons:", elevCH2
)
342 if rudderMode
== 1 then
343 drawNextLine(x
, y
, "Rudder:", rudCH1
)
345 lcd
.drawText(48, LCD_H
-8, "[Enter Long] to confirm", 0);
346 lcd
.drawFilledRectangle(0, LCD_H
-9, LCD_W
, 9, 0)
347 lcd
.drawPixmap(LCD_W
-18, 0, "confirm-tick.bmp")
348 lcd
.drawPixmap(0, LCD_H
-17, "confirm-plane.bmp")
352 local function confirmationMenu(event
)
355 drawConfirmationMenu()
358 navigate(event
, fieldsMax
, RUDDER_PAGE
, page
)
360 if event
== EVT_EXIT_BREAK
then
362 elseif event
== EVT_ENTER_LONG
then
373 local function run(event
)
375 error("Cannot be run as a model script!")
377 if servoPage
~= nil then
379 elseif page
== ENGINE_PAGE
then
381 elseif page
== ELEVONS_PAGE
then
383 elseif page
== RUDDER_PAGE
then
385 elseif page
== CONFIRMATION_PAGE
then
386 return confirmationMenu(event
)
391 return { init
=init
, run
=run
}