Shouldn't copyright be there too ? (#5200)
[opentx.git] / radio / sdcard / taranis-x9 / SCRIPTS / WIZARD / delta.lua
blobbc9a05ee80d9276f5594c39de5b25cb027230701
1 ---- #########################################################################
2 ---- # #
3 ---- # Copyright (C) OpenTX #
4 -----# #
5 ---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
6 ---- # #
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. #
10 ---- # #
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. #
15 ---- # #
16 ---- #########################################################################
17 -- Delta Wizard pages
18 local ENGINE_PAGE = 0
19 local ELEVONS_PAGE = 1
20 local RUDDER_PAGE = 2
21 local CONFIRMATION_PAGE = 3
23 -- Navigation variables
24 local page = ENGINE_PAGE
25 local dirty = true
26 local edit = false
27 local field = 0
28 local fieldsMax = 0
30 -- Model settings
31 local engineMode = 1
32 local thrCH1 = 0
33 local elevCH1 = 0
34 local elevCH2 = 0
35 local elevonsMode = 0
36 local rudderMode = 0
37 local rudCH1 = 0
38 local servoPage = nil
40 -- Common functions
41 local lastBlink = 0
42 local function blinkChanged()
43 local time = getTime() % 128
44 local blink = (time - time % 64) / 64
45 if blink ~= lastBlink then
46 lastBlink = blink
47 return true
48 else
49 return false
50 end
51 end
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
56 value = (value + max)
57 dirty = true
58 elseif event == EVT_MINUS_BREAK or event == EVT_ROT_RIGHT then
59 value = (value + max + 2)
60 dirty = true
61 end
62 value = (value % (max+1))
63 end
64 return value
65 end
67 local function valueIncDec(event, value, min, max)
68 if edit then
69 if event == EVT_PLUS_FIRST or event == EVT_PLUS_REPT or event == EVT_ROT_RIGHT then
70 if value < max then
71 value = (value + 1)
72 dirty = true
73 end
74 elseif event == EVT_MINUS_FIRST or event == EVT_MINUS_REPT or event == EVT_ROT_LEFT then
75 if value > min then
76 value = (value - 1)
77 dirty = true
78 end
79 end
80 end
81 return value
82 end
84 local function navigate(event, fieldMax, prevPage, nextPage)
85 if event == EVT_ENTER_BREAK then
86 edit = not edit
87 dirty = true
88 elseif edit then
89 if event == EVT_EXIT_BREAK then
90 edit = false
91 dirty = true
92 elseif not dirty then
93 dirty = blinkChanged()
94 end
95 else
96 if event == EVT_PAGE_BREAK then
97 page = nextPage
98 field = 0
99 dirty = true
100 elseif event == EVT_PAGE_LONG then
101 page = prevPage
102 field = 0
103 killEvents(event);
104 dirty = true
105 else
106 field = fieldIncDec(event, field, fieldMax, true)
111 local function getFieldFlags(position)
112 flags = 0
113 if field == position then
114 flags = INVERS
115 if edit then
116 flags = INVERS + BLINK
119 return flags
122 local function channelIncDec(event, value)
123 if not edit and event==EVT_MENU_BREAK then
124 servoPage = value
125 dirty = true
126 else
127 value = valueIncDec(event, value, 0, 15)
129 return value
132 -- Init function
133 local function init()
134 rudCH1 = defaultChannel(0)
135 thrCH1 = defaultChannel(2)
136 elevCH1 = defaultChannel(1)
137 elevCH2 = defaultChannel(3)
140 -- Engine Menu
141 local engineModeItems = {"No", "Yes..."}
142 local function drawEngineMenu()
143 lcd.clear()
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
149 -- No engine
150 lcd.drawPixmap(132, 8, "engine-0.bmp")
151 fieldsMax = 0
152 else
153 -- 1 channel
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))
158 fieldsMax = 1
162 local function engineMenu(event)
163 if dirty then
164 dirty = false
165 drawEngineMenu()
168 navigate(event, fieldsMax, page, page+1)
170 if field==0 then
171 engineMode = fieldIncDec(event, engineMode, 1)
172 elseif field==1 then
173 thrCH1 = channelIncDec(event, thrCH1)
177 -- Elevons Menu
178 local elevonsModeItems = {"2 Channels..."}
179 local function drawElevonsMenu()
180 lcd.clear()
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))
190 fieldsMax = 1
193 local function elevonsMenu(event)
194 if dirty then
195 dirty = false
196 drawElevonsMenu()
199 navigate(event, fieldsMax, page-1, page+1)
201 if field==0 then
202 elevCH1 = channelIncDec(event, elevCH1)
203 elseif field==1 then
204 elevCH2 = channelIncDec(event, elevCH2)
208 -- Rudder menu
209 local rudderModeItems = {"No", "Yes..."}
211 local function drawRudderMenu()
212 lcd.clear()
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
218 -- No rudder
219 lcd.drawPixmap(109, 14, "drudder-0.bmp")
220 fieldsMax = 0
221 else
222 -- 1 channel
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))
227 fieldsMax = 1
231 local function rudderMenu(event)
232 if dirty then
233 dirty = false
234 drawRudderMenu()
237 navigate(event, fieldsMax, page-1, page+1)
239 if field==0 then
240 rudderMode = fieldIncDec(event, rudderMode, 1)
241 elseif field==1 then
242 rudCH1 = channelIncDec(event, rudCH1)
246 -- Servo (limits) Menu
247 local function drawServoMenu(limits)
248 lcd.clear()
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));
260 else
261 lcd.drawText(129, 50, "\127", getFieldFlags(3));
263 fieldsMax = 3
266 local function servoMenu(event)
267 local limits = model.getOutput(servoPage)
269 if dirty then
270 dirty = false
271 drawServoMenu(limits)
274 navigate(event, fieldsMax, page, page)
276 if edit then
277 if field==0 then
278 limits.min = valueIncDec(event, limits.min, -1000, 0)
279 elseif field==1 then
280 limits.max = valueIncDec(event, limits.max, 0, 1000)
281 elseif field==2 then
282 limits.offset = valueIncDec(event, limits.offset, -1000, 1000)
283 elseif field==3 then
284 limits.revert = fieldIncDec(event, limits.revert, 1)
286 model.setOutput(servoPage, limits)
287 elseif event == EVT_EXIT_BREAK then
288 servoPage = nil
289 dirty = true
293 -- Confirmation Menu
294 local function addMix(channel, input, name, weight, index)
295 local mix = { source=input, name=name }
296 if weight ~= nil then
297 mix.weight = weight
299 if index == nil then
300 index = 0
302 model.insertMix(channel, index, mix)
305 local function applySettings()
306 model.defaultInputs()
307 model.deleteMixes()
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)
323 y = y + 8
324 if y > 50 then
325 y = 12
326 x = 120
328 return x, y
331 local function drawConfirmationMenu()
332 local x = 22
333 local y = 12
334 lcd.clear()
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")
349 fieldsMax = 0
352 local function confirmationMenu(event)
353 if dirty then
354 dirty = false
355 drawConfirmationMenu()
358 navigate(event, fieldsMax, RUDDER_PAGE, page)
360 if event == EVT_EXIT_BREAK then
361 return 2
362 elseif event == EVT_ENTER_LONG then
363 killEvents(event)
364 applySettings()
365 return 2
366 else
367 return 0
371 -- Main
373 local function run(event)
374 if event == nil then
375 error("Cannot be run as a model script!")
377 if servoPage ~= nil then
378 servoMenu(event)
379 elseif page == ENGINE_PAGE then
380 engineMenu(event)
381 elseif page == ELEVONS_PAGE then
382 elevonsMenu(event)
383 elseif page == RUDDER_PAGE then
384 rudderMenu(event)
385 elseif page == CONFIRMATION_PAGE then
386 return confirmationMenu(event)
388 return 0
391 return { init=init, run=run }