Initial Commit
This commit is contained in:
commit
933eee69e4
216 changed files with 20588 additions and 0 deletions
383
SCRIPTS/WIZARD/delta.lua
Executable file
383
SCRIPTS/WIZARD/delta.lua
Executable file
|
|
@ -0,0 +1,383 @@
|
|||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
-- Delta Wizard pages
|
||||
local ENGINE_PAGE = 0
|
||||
local ELEVONS_PAGE = 1
|
||||
local RUDDER_PAGE = 2
|
||||
local CONFIRMATION_PAGE = 3
|
||||
|
||||
-- Navigation variables
|
||||
local page = ENGINE_PAGE
|
||||
local dirty = true
|
||||
local edit = false
|
||||
local field = 0
|
||||
local fieldsMax = 0
|
||||
|
||||
-- Model settings
|
||||
local engineMode = 1
|
||||
local thrCH1 = 0
|
||||
local elevCH1 = 0
|
||||
local elevCH2 = 0
|
||||
local elevonsMode = 0
|
||||
local rudderMode = 0
|
||||
local rudCH1 = 0
|
||||
local servoPage = nil
|
||||
|
||||
-- Common functions
|
||||
local lastBlink = 0
|
||||
local function blinkChanged()
|
||||
local time = getTime() % 128
|
||||
local blink = (time - time % 64) / 64
|
||||
if blink ~= lastBlink then
|
||||
lastBlink = blink
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldIncDec(event, value, max, force)
|
||||
if edit or force==true then
|
||||
if event == EVT_VIRTUAL_INC then
|
||||
value = (value + max)
|
||||
dirty = true
|
||||
elseif event == EVT_VIRTUAL_DEC then
|
||||
value = (value + max + 2)
|
||||
dirty = true
|
||||
end
|
||||
value = (value % (max+1))
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function valueIncDec(event, value, min, max)
|
||||
if edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
if value < max then
|
||||
value = (value + 1)
|
||||
dirty = true
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
if value > min then
|
||||
value = (value - 1)
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function navigate(event, fieldMax, prevPage, nextPage)
|
||||
if event == EVT_VIRTUAL_ENTER then
|
||||
edit = not edit
|
||||
dirty = true
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
edit = false
|
||||
dirty = true
|
||||
elseif not dirty then
|
||||
dirty = blinkChanged()
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
page = nextPage
|
||||
field = 0
|
||||
dirty = true
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
||||
page = prevPage
|
||||
field = 0
|
||||
killEvents(event);
|
||||
dirty = true
|
||||
else
|
||||
field = fieldIncDec(event, field, fieldMax, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getFieldFlags(position)
|
||||
flags = 0
|
||||
if field == position then
|
||||
flags = INVERS
|
||||
if edit then
|
||||
flags = INVERS + BLINK
|
||||
end
|
||||
end
|
||||
return flags
|
||||
end
|
||||
|
||||
local function channelIncDec(event, value)
|
||||
if not edit and event==EVT_VIRTUAL_MENU then
|
||||
servoPage = value
|
||||
dirty = true
|
||||
else
|
||||
value = valueIncDec(event, value, 0, 15)
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
-- Init function
|
||||
local function init()
|
||||
rudCH1 = defaultChannel(0)
|
||||
thrCH1 = defaultChannel(2)
|
||||
elevCH1 = defaultChannel(1)
|
||||
elevCH2 = defaultChannel(3)
|
||||
end
|
||||
|
||||
-- Engine Menu
|
||||
local engineModeItems = {"No", "Yes"}
|
||||
local function drawEngineMenu()
|
||||
lcd.clear()
|
||||
if engineMode == 0 then
|
||||
-- No engine
|
||||
fieldsMax = 0
|
||||
else
|
||||
-- 1 channel
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+thrCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
end
|
||||
lcd.drawText(1, 0, "Got an engine?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, engineModeItems, engineMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function engineMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawEngineMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page, page+1)
|
||||
|
||||
if field==0 then
|
||||
engineMode = fieldIncDec(event, engineMode, 1)
|
||||
elseif field==1 then
|
||||
thrCH1 = channelIncDec(event, thrCH1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Elevons Menu
|
||||
local elevonsModeItems = {"2 Channels"}
|
||||
local function drawElevonsMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Select elevon channnels", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, elevonsModeItems, elevonsMode, 0)
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(30, 40, "L", 0);
|
||||
lcd.drawText(65, 40, "R", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+elevCH1, getFieldFlags(0))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+elevCH2, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
end
|
||||
|
||||
local function elevonsMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawElevonsMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
|
||||
if field==0 then
|
||||
elevCH1 = channelIncDec(event, elevCH1)
|
||||
elseif field==1 then
|
||||
elevCH2 = channelIncDec(event, elevCH2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Rudder menu
|
||||
local rudderModeItems = {"No", "Yes"}
|
||||
|
||||
local function drawRudderMenu()
|
||||
lcd.clear()
|
||||
if rudderMode == 0 then
|
||||
-- No rudder
|
||||
fieldsMax = 0
|
||||
else
|
||||
-- 1 channel
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+rudCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
end
|
||||
lcd.drawText(1, 0, "Got a rudder?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, rudderModeItems, rudderMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function rudderMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawRudderMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
|
||||
if field==0 then
|
||||
rudderMode = fieldIncDec(event, rudderMode, 1)
|
||||
elseif field==1 then
|
||||
rudCH1 = channelIncDec(event, rudCH1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Servo (limits) Menu
|
||||
local function drawServoMenu(limits)
|
||||
lcd.clear()
|
||||
lcd.drawSource(1, 0, MIXSRC_CH1+servoPage, 0)
|
||||
lcd.drawText(25, 0, "servo min/max/center/direction?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawText(LCD_W/2-19, LCD_H-8, ">>>", 0);
|
||||
lcd.drawNumber(140, 35, limits.min, PREC1+getFieldFlags(0));
|
||||
lcd.drawNumber(205, 35, limits.max, PREC1+getFieldFlags(1));
|
||||
lcd.drawNumber(170, 9, limits.offset, PREC1+getFieldFlags(2));
|
||||
if limits.revert == 0 then
|
||||
lcd.drawText(129, 50, "\126", getFieldFlags(3));
|
||||
else
|
||||
lcd.drawText(129, 50, "\127", getFieldFlags(3));
|
||||
end
|
||||
fieldsMax = 3
|
||||
end
|
||||
|
||||
local function servoMenu(event)
|
||||
local limits = model.getOutput(servoPage)
|
||||
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawServoMenu(limits)
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page, page)
|
||||
|
||||
if edit then
|
||||
if field==0 then
|
||||
limits.min = valueIncDec(event, limits.min, -1000, 0)
|
||||
elseif field==1 then
|
||||
limits.max = valueIncDec(event, limits.max, 0, 1000)
|
||||
elseif field==2 then
|
||||
limits.offset = valueIncDec(event, limits.offset, -1000, 1000)
|
||||
elseif field==3 then
|
||||
limits.revert = fieldIncDec(event, limits.revert, 1)
|
||||
end
|
||||
model.setOutput(servoPage, limits)
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
servoPage = nil
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Confirmation Menu
|
||||
local function addMix(channel, input, name, weight, index)
|
||||
local mix = { source=input, name=name }
|
||||
if weight ~= nil then
|
||||
mix.weight = weight
|
||||
end
|
||||
if index == nil then
|
||||
index = 0
|
||||
end
|
||||
model.insertMix(channel, index, mix)
|
||||
end
|
||||
|
||||
local function applySettings()
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
if engineMode == 1 then
|
||||
addMix(thrCH1, MIXSRC_FIRST_INPUT+defaultChannel(2), "Engine")
|
||||
end
|
||||
addMix(elevCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "D-EleL", 50)
|
||||
addMix(elevCH1, MIXSRC_FIRST_INPUT+defaultChannel(3), "D-AilL", 50, 1)
|
||||
addMix(elevCH2, MIXSRC_FIRST_INPUT+defaultChannel(1), "D-EleR", 50)
|
||||
addMix(elevCH2, MIXSRC_FIRST_INPUT+defaultChannel(3), "D-AilR", -50, 1)
|
||||
if rudderMode == 1 then
|
||||
addMix(rudCH1, MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder")
|
||||
end
|
||||
end
|
||||
|
||||
local function drawNextLine(x, y, label, channel)
|
||||
lcd.drawText(x, y, label, 0);
|
||||
lcd.drawText(x+48, y, ":", 0);
|
||||
lcd.drawSource(x+52, y, MIXSRC_CH1+channel, 0)
|
||||
y = y + 8
|
||||
if y > 50 then
|
||||
y = 12
|
||||
x = 120
|
||||
end
|
||||
return x, y
|
||||
end
|
||||
|
||||
local function drawConfirmationMenu()
|
||||
local x = 22
|
||||
local y = 12
|
||||
lcd.clear()
|
||||
lcd.drawText(48, 1, "Ready to go?", 0);
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 9, 0)
|
||||
if engineMode == 1 then
|
||||
x, y = drawNextLine(x, y, "Throttle", thrCH1)
|
||||
end
|
||||
x, y = drawNextLine(x, y, "Elevon L", elevCH1)
|
||||
x, y = drawNextLine(x, y, "Elevon R", elevCH2)
|
||||
if rudderMode == 1 then
|
||||
drawNextLine(x, y, "Rudder", rudCH1)
|
||||
end
|
||||
lcd.drawText(0, LCD_H-8, "[Enter Long] to confirm", 0);
|
||||
lcd.drawFilledRectangle(0, LCD_H-9, LCD_W, 9, 0)
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function confirmationMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawConfirmationMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, RUDDER_PAGE, page)
|
||||
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER_LONG then
|
||||
killEvents(event)
|
||||
applySettings()
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Main
|
||||
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
end
|
||||
|
||||
if servoPage ~= nil then
|
||||
servoMenu(event)
|
||||
elseif page == ENGINE_PAGE then
|
||||
engineMenu(event)
|
||||
elseif page == ELEVONS_PAGE then
|
||||
elevonsMenu(event)
|
||||
elseif page == RUDDER_PAGE then
|
||||
rudderMenu(event)
|
||||
elseif page == CONFIRMATION_PAGE then
|
||||
return confirmationMenu(event)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
533
SCRIPTS/WIZARD/heli.lua
Executable file
533
SCRIPTS/WIZARD/heli.lua
Executable file
|
|
@ -0,0 +1,533 @@
|
|||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) EdgeTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
local switches = {"SA", "SB", "SC", "SD", "SF"}
|
||||
local switchValues = {[0]=2, 5, 8, 11, 14}
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[3] == VALUE then
|
||||
min = field[6]
|
||||
max = field[7]
|
||||
elseif field[3] == COMBO then
|
||||
min = 0
|
||||
max = #(field[6]) - 1
|
||||
end
|
||||
if (step < 0 and field[5] > min) or (step > 0 and field[5] < max) then
|
||||
field[5] = field[5] + step
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
page = 1 + ((page + step - 1 + #pages) % #pages)
|
||||
edit = false
|
||||
current = 1
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
repeat
|
||||
current = 1 + ((current + step - 1 + #fields) % #fields)
|
||||
until fields[current][4]==1
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage(event)
|
||||
|
||||
for index = 1, 10, 1 do
|
||||
local field = fields[index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local attr = current == (index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
attr = attr
|
||||
|
||||
if field[4] == 1 then
|
||||
if field[3] == VALUE then
|
||||
lcd.drawNumber(field[1], field[2], field[5], LEFT + attr)
|
||||
elseif field[3] == COMBO then
|
||||
if field[5] >= 0 and field[5] < #(field[6]) then
|
||||
lcd.drawText(field[1],field[2], field[6][1+field[5]], attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[5]
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
if fields[current][5] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
lcd.clear()
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage(event)
|
||||
return 0
|
||||
end
|
||||
|
||||
-- set visibility flags starting with SECOND field of fields
|
||||
local function setFieldsVisible(...)
|
||||
local arg={...}
|
||||
local cnt = 2
|
||||
for i,v in ipairs(arg) do
|
||||
fields[cnt][4] = v
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
|
||||
local TypeFields = {
|
||||
{0, 12, COMBO, 1, 0, {"Flybarless (FBL)", "Flybarred (FB)" } },
|
||||
{65, 25, COMBO, 1, 0, {"120", "120X", "140", "90" } },
|
||||
}
|
||||
|
||||
local function runTypeConfig(event)
|
||||
lcd.clear()
|
||||
fields = TypeFields
|
||||
lcd.drawScreenTitle("Helicopter Type", 1,9)
|
||||
fields[2][4] = 0
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawText(0, 25, "Swash Type")
|
||||
fields[2][4] = 1
|
||||
end
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local StyleFields = {
|
||||
{0, 12, COMBO, 1, 0, { "Sport", "Light 3D","Full 3D" } },
|
||||
}
|
||||
|
||||
local function runStyleConfig(event)
|
||||
lcd.clear()
|
||||
fields = StyleFields
|
||||
lcd.drawScreenTitle("Your Flying Style",2,9)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local SwitchFields = {
|
||||
{75, 12, COMBO, 1, 0, { "SA", "SB", "SC", "SD","SF" } },
|
||||
{75, 33, COMBO, 1, 4, { "SA", "SB", "SC", "SD","SF" } },
|
||||
{75, 54, COMBO, 1, 2, { "SA", "SB", "SC", "SD", "SF" } },
|
||||
}
|
||||
|
||||
local function runSwitchConfig(event)
|
||||
lcd.clear()
|
||||
lcd.drawScreenTitle("Assign Switches",3,9)
|
||||
fields = SwitchFields
|
||||
lcd.drawText(0, 12, "FM (Idle Up)")
|
||||
fields[1][4]=1
|
||||
lcd.drawText(0, 33, "Throttle Hold")
|
||||
fields[2][4]=1
|
||||
fields[3][4]=0
|
||||
if TypeFields[1][5]==1 then
|
||||
lcd.drawText(0, 54, "Tail Gain")
|
||||
fields[3][4]=1
|
||||
end
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local ThrFields = {
|
||||
{0, 12, COMBO, 1, 2, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local function runThrConfig(event)
|
||||
lcd.clear()
|
||||
fields = ThrFields
|
||||
lcd.drawScreenTitle("Throttle Channel",3,9)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local CurveFields = {
|
||||
{75, 12, COMBO, 1, 0, { "Thr Up", "V Curve","Flat" } },
|
||||
{75, 32, COMBO, 1, 0, { "V Curve","Flat" } },
|
||||
{75, 54, COMBO, 1, 0, { "V Curve","Flat" } },
|
||||
}
|
||||
|
||||
local function runCurveConfig(event)
|
||||
lcd.clear()
|
||||
fields = CurveFields
|
||||
lcd.drawScreenTitle("FM Throttle Curves",4,9)
|
||||
lcd.drawText(0, 12, "FM0 Curve")
|
||||
fields[1][4]=1
|
||||
lcd.drawText(0, 32, "FM1 Curve")
|
||||
fields[2][4]=1
|
||||
lcd.drawText(0, 54, "FM2 Curve")
|
||||
fields[3][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local AilerFields = {
|
||||
{0, 12, COMBO, 1, 0, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local function runAilerConfig(event)
|
||||
lcd.clear()
|
||||
fields = AilerFields
|
||||
lcd.drawScreenTitle("Aileron Channel",5,9)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local EleFields = {
|
||||
{0, 12, COMBO, 1, 1, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local function runEleConfig(event)
|
||||
lcd.clear()
|
||||
fields = EleFields
|
||||
lcd.drawScreenTitle("Elevator Channel",6,9)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local RudFields = {
|
||||
{0, 12, COMBO, 1, 3, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local function runRudConfig(event)
|
||||
lcd.clear()
|
||||
fields = RudFields
|
||||
lcd.drawScreenTitle("Rudder (Tail) Channel",7,9)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local lineIndex
|
||||
|
||||
local function drawNextChanelLine(text, text2)
|
||||
lcd.drawText(0, lineIndex, text)
|
||||
lcd.drawText(55, lineIndex, ": CH" .. text2 + 1)
|
||||
lineIndex = lineIndex + 9
|
||||
end
|
||||
|
||||
local function drawNextSwitchLine(text, text2)
|
||||
lcd.drawText(0, lineIndex, text)
|
||||
lcd.drawText(55, lineIndex, ": " ..switches[text2 + 1])
|
||||
lineIndex = lineIndex + 9
|
||||
end
|
||||
|
||||
local function drawNextTextLine(text, text2)
|
||||
lcd.drawText(0, lineIndex, text)
|
||||
lcd.drawText(55, lineIndex, ": " ..text2)
|
||||
lineIndex = lineIndex + 9
|
||||
end
|
||||
|
||||
local function switchLine(text)
|
||||
text=SwitchFields[2][5]
|
||||
getFieldInfo(text)
|
||||
swnum=text.id
|
||||
end
|
||||
|
||||
local SummaryFields = {
|
||||
{0, 56, {1}},
|
||||
}
|
||||
|
||||
local function runSummary(event)
|
||||
lcd.clear()
|
||||
lcd.drawScreenTitle("Summary", 8,9)
|
||||
fields = SummaryFields
|
||||
lineIndex = 9
|
||||
|
||||
-- Type
|
||||
if TypeFields[1][5]==0 then
|
||||
drawNextTextLine("TYPE","FBL")
|
||||
else
|
||||
drawNextTextLine("TYPE","FB")
|
||||
if TypeFields[2][5]==0 then
|
||||
lcd.drawText(75,9,"120")
|
||||
elseif TypeFields[2][5]==1 then
|
||||
lcd.drawText(75,9,"120X")
|
||||
elseif TypeFields[2][5]==2 then
|
||||
lcd.drawText(75,9,"140")
|
||||
else
|
||||
lcd.drawText(75,9,"90")
|
||||
end
|
||||
end
|
||||
|
||||
-- Style
|
||||
if StyleFields[1][5]==0 then
|
||||
drawNextTextLine("Style","Sport")
|
||||
elseif StyleFields[1][5]==1 then
|
||||
drawNextTextLine("Style","Light 3D")
|
||||
else
|
||||
drawNextTextLine("Style","Full 3D")
|
||||
end
|
||||
|
||||
-- Switch
|
||||
drawNextSwitchLine("FM SW",SwitchFields[1][5])
|
||||
drawNextSwitchLine("Th Hold SW",SwitchFields[2][5])
|
||||
if TypeFields[1][5]==1 then
|
||||
drawNextSwitchLine("Gyro SW",SwitchFields[3][5])
|
||||
end
|
||||
|
||||
-- thr
|
||||
drawNextChanelLine("Throttle",ThrFields[1][5])
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local ConfigSummaryFields = {
|
||||
{10, 50,{1}},
|
||||
}
|
||||
|
||||
local function runConfigSummary(event)
|
||||
lcd.clear()
|
||||
lcd.drawScreenTitle("Long Enter -> Create", 9,9)
|
||||
fields = ConfigSummaryFields
|
||||
lineIndex = 8
|
||||
|
||||
-- FM0 Curve
|
||||
if CurveFields[1][5]==0 then
|
||||
drawNextTextLine("FM0 Curve","Throttle Up")
|
||||
elseif CurveFields[1][5]==1 then
|
||||
drawNextTextLine("FM0 Curve","V Style")
|
||||
else
|
||||
drawNextTextLine("FM0 Curve","Flat Style")
|
||||
end
|
||||
|
||||
-- FM1 Curve
|
||||
if CurveFields[2][5]==0 then
|
||||
drawNextTextLine("FM1 Curve","V Style")
|
||||
else
|
||||
drawNextTextLine("FM1 Curve","Flat Style")
|
||||
end
|
||||
|
||||
-- FM3 Curve
|
||||
if CurveFields[3][5]==0 then
|
||||
drawNextTextLine("FM2 Curve","V Style")
|
||||
else
|
||||
drawNextTextLine("FM2 Curve","Flat Style")
|
||||
end
|
||||
|
||||
-- Ail
|
||||
drawNextChanelLine("Aileron",AilerFields[1][5])
|
||||
|
||||
-- Elev
|
||||
drawNextChanelLine("Elevator",EleFields[1][5])
|
||||
|
||||
-- Rudder
|
||||
drawNextChanelLine("Rudder",RudFields[1][5])
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local function runCreateModel(event)
|
||||
lcd.clear()
|
||||
local b = SwitchFields[1][5]
|
||||
local tUp = switchValues[b]
|
||||
local i = SwitchFields[2][5]
|
||||
local hold = switchValues[i]
|
||||
local f = SwitchFields[3][5]
|
||||
local gyRate = switchValues[f]
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
|
||||
-- Curve Fm0
|
||||
if StyleFields[1][5]==0 and CurveFields[1][5]==0 then
|
||||
model.setCurve(0,{name="TC0",y={-100, 0, 0, 40, 40}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[1][5]==0 then
|
||||
model.setCurve(0,{name="TC0",y={-100, 0, 35, 50, 50}})
|
||||
elseif StyleFields[1][5]==2 and CurveFields[1][5]==0 then
|
||||
model.setCurve(0,{name="TC0",y={-100, 0, 40, 80, 80}})
|
||||
elseif StyleFields[1][5]==0 and CurveFields[1][5]==1 then
|
||||
model.setCurve(0,{name="TC0",y={50, 40, 50}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[1][5]==1 then
|
||||
model.setCurve(0,{name="TC0",y={65, 55, 65}})
|
||||
elseif StyleFields[1][5]==2 and CurveFields[1][5]==1 then
|
||||
model.setCurve(0,{name="TC0",y={70, 60, 70}})
|
||||
elseif StyleFields[1][5]==0 and CurveFields[1][5]==2 then
|
||||
model.setCurve(0,{name="TC0",y={60,60,60}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[1][5]==2 then
|
||||
model.setCurve(0,{name="TC0",y={65,65,65}})
|
||||
else
|
||||
model.setCurve(0,{name="TC0",y={70,70,70}})
|
||||
end
|
||||
|
||||
--Curve FM1
|
||||
if StyleFields[1][5]==0 and CurveFields[2][5]==0 then
|
||||
model.setCurve(1,{name="TC1",y={60, 50, 60}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[2][5]==0 then
|
||||
model.setCurve(1,{name="TC1",y={70, 60, 70}})
|
||||
elseif StyleFields[1][5]==2 and CurveFields[2][5]==0 then
|
||||
model.setCurve(1,{name="TC1",y={85, 75, 85}})
|
||||
elseif StyleFields[1][5]==0 and CurveFields[2][5]==1 then
|
||||
model.setCurve(1,{name="TC1",y={65,65,65}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[2][5]==1 then
|
||||
model.setCurve(1,{name="TC1",y={70,70,70}})
|
||||
else
|
||||
model.setCurve(1,{name="TC1",y={85 ,85,85}})
|
||||
end
|
||||
|
||||
--Curve FM2
|
||||
if StyleFields[1][5]>=0 and CurveFields[3][5]==0 then
|
||||
model.setCurve(2,{name="TC2",y={70, 60, 70}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[3][5]==0 then
|
||||
model.setCurve(2,{name="TC2",y={85, 70, 85}})
|
||||
elseif StyleFields[1][5]==2 and CurveFields[3][5]==0 then
|
||||
model.setCurve(2,{name="TC2",y={100, 90, 100}})
|
||||
elseif StyleFields[1][5]==0 and CurveFields[3][5]==1 then
|
||||
model.setCurve(2,{name="TC2",y={75 ,75,75}})
|
||||
elseif StyleFields[1][5]==1 and CurveFields[3][5]==1 then
|
||||
model.setCurve(2,{name="TC2",y={85 ,85, 85}})
|
||||
else
|
||||
model.setCurve(2,{name="TC2",y={95 ,95, 95}})
|
||||
end
|
||||
|
||||
--Curve TH Hold
|
||||
model.setCurve(3,{name="THD",y={-100,-100,-100}})
|
||||
|
||||
-- Throttle
|
||||
model.insertMix(ThrFields[1][5], 0,{name="Th0",weight=100,curveType=3,curveValue=1})
|
||||
model.insertMix(ThrFields[1][5], 1,{name="Th1",weight=100,switch=tUp,multiplex=2,curveType=3,curveValue=2})
|
||||
model.insertMix(ThrFields[1][5], 2,{name="Th2",weight=100,switch=tUp-1,multiplex=2,curveType=3,curveValue=3})
|
||||
model.insertMix(ThrFields[1][5], 3,{name="Hld",weight=100,offset=-15,switch=hold+1,multiplex=2,curveType=3,curveValue=4})
|
||||
model.setOutput(ThrFields[1][5],{name="Thrt"})
|
||||
|
||||
-- Ail
|
||||
if TypeFields[1][5] == 0 then
|
||||
model.insertMix(AilerFields[1][5], 0,{name="Ail",weight=100})
|
||||
model.setOutput(AilerFields[1][5],{name="Aile"})
|
||||
else
|
||||
model.insertMix(AilerFields[1][5], 0,{source=83,name="Ail",weight=100})
|
||||
model.setOutput(AilerFields[1][5],{name="Aile"})
|
||||
end
|
||||
|
||||
-- Elev
|
||||
if TypeFields[1][5] == 0 then
|
||||
model.insertMix(EleFields[1][5], 0,{name="Ele",weight=100})
|
||||
model.setOutput(EleFields[1][5],{name="Elev"})
|
||||
else
|
||||
model.insertMix(EleFields[1][5], 0,{source=82,name="Ele",weight=100})
|
||||
model.setOutput(EleFields[1][5],{name="Elev"})
|
||||
end
|
||||
|
||||
-- Rudder
|
||||
model.insertMix(RudFields[1][5], 0,{name="Rud",weight=100})
|
||||
model.setOutput(RudFields[1][5],{name="Rud"})
|
||||
|
||||
-- Gyro
|
||||
if TypeFields[1][5] == 0 then
|
||||
model.insertMix(4, 0,{source=81,name="T.Ga",weight=25})
|
||||
model.setOutput(4,{name="T.Ga"})
|
||||
else
|
||||
model.insertMix( 4, 0,{source=81,name="HHold",weight=25})
|
||||
model.insertMix( 4, 1,{source=81,name="Rate",weight=-25,switch=gyRate,multiplex=2})
|
||||
model.setOutput(4,{name="T.Ga"})
|
||||
end
|
||||
|
||||
-- Pitch
|
||||
if TypeFields[1][5] == 0 then
|
||||
model.insertMix(5, 0,{source=77,name="Pch",weight=100})
|
||||
model.setOutput(5,{name="Ptch"})
|
||||
else
|
||||
model.insertMix(5, 0,{source=84,name="Pch",weight=100})
|
||||
model.setOutput(5,{name="Ptch"})
|
||||
end
|
||||
|
||||
--Set Swash Parameters
|
||||
if TypeFields[1][5]==1 and TypeFields[2][5]==0 then
|
||||
model.setSwashRing({type="1",collectiveSource=77,aileronSource=78,elevatorSource=76,collectiveWeight=60,aileronWeight=60,elevatorWeight=60})
|
||||
elseif TypeFields[2][5]==1 then
|
||||
model.setSwashRing({type="2",collectiveSource=77,aileronSource=78,elevatorSource=76,collectiveWeight=60,aileronWeight=60,elevatorWeight=60})
|
||||
elseif TypeFields[2][5]==2 then
|
||||
model.setSwashRing({type="3",collectiveSource=77,aileronSource=78,elevatorSource=76,collectiveWeight=40,aileronWeight=40,elevatorWeight=60})
|
||||
elseif TypeFields[2][5]==3 then
|
||||
model.setSwashRing({type="4",collectiveSource=77,aileronSource=78,elevatorSource=76,collectiveWeight=35,aileronWeight=35,elevatorWeight=60})
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit = 1, false
|
||||
pages = {
|
||||
runTypeConfig,
|
||||
runStyleConfig,
|
||||
runSwitchConfig,
|
||||
runThrConfig,
|
||||
runCurveConfig,
|
||||
runAilerConfig,
|
||||
runEleConfig,
|
||||
runRudConfig,
|
||||
runSummary,
|
||||
runConfigSummary,
|
||||
}
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE and page < #pages then
|
||||
selectPage(1)
|
||||
elseif event == EVT_VIRTUAL_ENTER_LONG and page == #pages then
|
||||
runCreateModel(event)
|
||||
lcd.drawText(0,15,"Model Sucessfully created !")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE and page > 1 then
|
||||
killEvents(event);
|
||||
selectPage(-1)
|
||||
end
|
||||
local result = pages[page](event)
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
440
SCRIPTS/WIZARD/multi.lua
Executable file
440
SCRIPTS/WIZARD/multi.lua
Executable file
|
|
@ -0,0 +1,440 @@
|
|||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
-- Multicopter Wizard pages
|
||||
local THROTTLE_PAGE = 0
|
||||
local ROLL_PAGE = 1
|
||||
local PITCH_PAGE = 2
|
||||
local YAW_PAGE = 3
|
||||
local ARM_PAGE = 4
|
||||
local MODE_PAGE = 5
|
||||
local BEEPER_PAGE = 6
|
||||
local CONFIRMATION_PAGE = 7
|
||||
|
||||
-- Navigation variables
|
||||
local page = THROTTLE_PAGE
|
||||
local dirty = true
|
||||
local edit = false
|
||||
local field = 0
|
||||
local fieldsMax = 0
|
||||
local comboBoxMode = 0 -- Scrap variable
|
||||
local validSwitch = {}
|
||||
|
||||
-- Model settings
|
||||
local thrCH1 = 0
|
||||
local rollCH1 = 0
|
||||
local yawCH1 = 0
|
||||
local pitchCH1 = 0
|
||||
local armSW1 = 1
|
||||
local beeperSW1 = 1
|
||||
local modeSW1 = 1
|
||||
local switches = {}
|
||||
|
||||
-- Common functions
|
||||
local lastBlink = 0
|
||||
local function blinkChanged()
|
||||
local time = getTime() % 128
|
||||
local blink = (time - time % 64) / 64
|
||||
if blink ~= lastBlink then
|
||||
lastBlink = blink
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldIncDec(event, value, max, force)
|
||||
if edit or force==true then
|
||||
if event == EVT_VIRTUAL_INC then
|
||||
value = (value + max)
|
||||
dirty = true
|
||||
elseif event == EVT_VIRTUAL_DEC then
|
||||
value = (value + max + 2)
|
||||
dirty = true
|
||||
end
|
||||
value = (value % (max+1))
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function valueIncDec(event, value, min, max)
|
||||
if edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
if value < max then
|
||||
value = (value + 1)
|
||||
dirty = true
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
if value > min then
|
||||
value = (value - 1)
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function navigate(event, fieldMax, prevPage, nextPage)
|
||||
if event == EVT_VIRTUAL_ENTER then
|
||||
edit = not edit
|
||||
dirty = true
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
edit = false
|
||||
dirty = true
|
||||
elseif not dirty then
|
||||
dirty = blinkChanged()
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
page = nextPage
|
||||
field = 0
|
||||
dirty = true
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
||||
page = prevPage
|
||||
field = 0
|
||||
killEvents(event);
|
||||
dirty = true
|
||||
else
|
||||
field = fieldIncDec(event, field, fieldMax, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getFieldFlags(position)
|
||||
flags = 0
|
||||
if field == position then
|
||||
flags = INVERS
|
||||
if edit then
|
||||
flags = INVERS + BLINK
|
||||
end
|
||||
end
|
||||
return flags
|
||||
end
|
||||
|
||||
local function channelIncDec(event, value)
|
||||
if not edit and event==EVT_VIRTUAL_MENU then
|
||||
servoPage = value
|
||||
dirty = true
|
||||
else
|
||||
value = valueIncDec(event, value, 0, 15)
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function switchValueIncDec(event, value, min, max)
|
||||
if edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
if value < max then
|
||||
value = (value + 1)
|
||||
dirty = true
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
if value > min then
|
||||
value = (value - 1)
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function switchIncDec(event, value)
|
||||
if not edit and event== EVT_VIRTUAL_MENU then
|
||||
servoPage = value
|
||||
dirty = true
|
||||
else
|
||||
value = switchValueIncDec(event, value, 1, #switches)
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
-- Init function
|
||||
local function init()
|
||||
thrCH1 = defaultChannel(2)
|
||||
rollCH1 = defaultChannel(3)
|
||||
yawCH1 = defaultChannel(0)
|
||||
pitchCH1 = defaultChannel(1)
|
||||
local ver, radio, maj, minor, rev = getVersion()
|
||||
if string.match(radio, "x7") then
|
||||
switches = {"SA", "SB", "SC", "SD", "SF", "SH"}
|
||||
elseif string.match(radio, "tx12") then
|
||||
switches = {"SA", "SB", "SC", "SD", "SE", "SF"}
|
||||
else
|
||||
switches = {"SA", "SB", "SC", "SD"}
|
||||
end
|
||||
end
|
||||
|
||||
-- Throttle Menu
|
||||
local function drawThrottleMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Throttle"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+thrCH1, getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function throttleMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawThrottleMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page, page+1)
|
||||
thrCH1 = channelIncDec(event, thrCH1)
|
||||
end
|
||||
|
||||
-- Roll Menu
|
||||
local function drawRollMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Roll"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+rollCH1, getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function rollMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawRollMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
rollCH1 = channelIncDec(event, rollCH1)
|
||||
end
|
||||
|
||||
-- Pitch Menu
|
||||
local function drawPitchMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Pitch"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+pitchCH1, getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function pitchMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawPitchMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
pitchCH1 = channelIncDec(event, pitchCH1)
|
||||
end
|
||||
|
||||
-- Yaw Menu
|
||||
local function drawYawMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Yaw"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+yawCH1, getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function yawMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawYawMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
yawCH1 = channelIncDec(event, yawCH1)
|
||||
end
|
||||
|
||||
-- Arm Menu
|
||||
local function drawArmMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Arm"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign AUX1", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawText(25, 40, switches[armSW1], getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function armMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawArmMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
armSW1 = switchIncDec(event, armSW1)
|
||||
end
|
||||
|
||||
-- Beeper Menu
|
||||
local function drawbeeperMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Beeper"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign AUX2", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawText(25, 40, switches[beeperSW1], getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function beeperMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawbeeperMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
beeperSW1 = switchIncDec(event, beeperSW1)
|
||||
end
|
||||
|
||||
-- Mode Menu
|
||||
local function drawmodeMenu()
|
||||
lcd.clear()
|
||||
lcd.drawText(1, 0, "Multicopter", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, {"Mode"}, comboBoxMode, getFieldFlags(1))
|
||||
lcd.drawText(5, 30, "Assign AUX3", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawText(25, 40, switches[modeSW1], getFieldFlags(0))
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function modeMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawmodeMenu()
|
||||
end
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
modeSW1 = switchIncDec(event, modeSW1)
|
||||
end
|
||||
|
||||
-- Confirmation Menu
|
||||
local function drawNextLine(x, y, label, channel)
|
||||
lcd.drawText(x, y, label, 0);
|
||||
lcd.drawText(x+46, y, ":", 0);
|
||||
lcd.drawSource(x+50, y, MIXSRC_CH1+channel, 0)
|
||||
y = y + 8
|
||||
if y > 50 then
|
||||
y = 12
|
||||
x = 120
|
||||
end
|
||||
return x, y
|
||||
end
|
||||
|
||||
local function drawNextSWLine(x, y, label, switch)
|
||||
lcd.drawText(x, y, label, 0);
|
||||
lcd.drawText(x+38, y, ":", 0);
|
||||
lcd.drawText(x+42, y, switches[switch], 0)
|
||||
y = y + 8
|
||||
if y > 50 then
|
||||
y = 12
|
||||
x = 120
|
||||
end
|
||||
return x, y
|
||||
end
|
||||
|
||||
local function drawConfirmationMenu()
|
||||
local x = 1
|
||||
local y = 12
|
||||
lcd.clear()
|
||||
lcd.drawText(0, 1, "Ready to go?", 0);
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 9, 0)
|
||||
x, y = drawNextLine(x, y, "Throttle", thrCH1)
|
||||
x, y = drawNextLine(x, y, "Roll", rollCH1)
|
||||
x, y = drawNextLine(x, y, "Pitch", pitchCH1)
|
||||
x, y = drawNextLine(x, y, "Yaw", yawCH1)
|
||||
local x = 72
|
||||
local y = 12
|
||||
x, y = drawNextSWLine(x, y, "Arm", armSW1)
|
||||
x, y = drawNextSWLine(x, y, "Mode", modeSW1)
|
||||
x, y = drawNextSWLine(x, y, "Beeper", beeperSW1)
|
||||
lcd.drawText(0, LCD_H-8, "[Enter Long] to confirm", 0);
|
||||
lcd.drawFilledRectangle(0, LCD_H-9, LCD_W, 9, 0)
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function addMix(channel, input, name, weight, index)
|
||||
local mix = { source=input, name=name }
|
||||
if weight ~= nil then
|
||||
mix.weight = weight
|
||||
end
|
||||
if index == nil then
|
||||
index = 0
|
||||
end
|
||||
model.insertMix(channel, index, mix)
|
||||
end
|
||||
|
||||
local function applySettings()
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
addMix(thrCH1, MIXSRC_FIRST_INPUT+defaultChannel(2), "Throttle")
|
||||
addMix(rollCH1, MIXSRC_FIRST_INPUT+defaultChannel(3), "Roll")
|
||||
addMix(yawCH1, MIXSRC_FIRST_INPUT+defaultChannel(0), "Yaw")
|
||||
addMix(pitchCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "Pitch")
|
||||
addMix(4, MIXSRC_SA + armSW1 - 1, "Arm")
|
||||
addMix(5, MIXSRC_SA + beeperSW1 - 1, "Beeper")
|
||||
addMix(6, MIXSRC_SA + modeSW1 - 1, "Mode")
|
||||
end
|
||||
|
||||
local function confirmationMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawConfirmationMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, BEEPER_PAGE, page)
|
||||
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER_LONG then
|
||||
killEvents(event)
|
||||
applySettings()
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
end
|
||||
if page == THROTTLE_PAGE then
|
||||
throttleMenu(event)
|
||||
elseif page == ROLL_PAGE then
|
||||
rollMenu(event)
|
||||
elseif page == YAW_PAGE then
|
||||
yawMenu(event)
|
||||
elseif page == PITCH_PAGE then
|
||||
pitchMenu(event)
|
||||
elseif page == ARM_PAGE then
|
||||
armMenu(event)
|
||||
elseif page == BEEPER_PAGE then
|
||||
beeperMenu(event)
|
||||
elseif page == MODE_PAGE then
|
||||
modeMenu(event)
|
||||
elseif page == CONFIRMATION_PAGE then
|
||||
return confirmationMenu(event)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
582
SCRIPTS/WIZARD/plane.lua
Executable file
582
SCRIPTS/WIZARD/plane.lua
Executable file
|
|
@ -0,0 +1,582 @@
|
|||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
-- Plane Wizard pages
|
||||
local ENGINE_PAGE = 0
|
||||
local AILERONS_PAGE = 1
|
||||
local FLAPERONS_PAGE = 2
|
||||
local BRAKES_PAGE = 3
|
||||
local TAIL_PAGE = 4
|
||||
local CONFIRMATION_PAGE = 5
|
||||
|
||||
-- Navigation variables
|
||||
local page = ENGINE_PAGE
|
||||
local dirty = true
|
||||
local edit = false
|
||||
local field = 0
|
||||
local fieldsMax = 0
|
||||
|
||||
-- Model settings
|
||||
local engineMode = 1
|
||||
local thrCH1 = 0
|
||||
local aileronsMode = 1
|
||||
local ailCH1 = 0
|
||||
local ailCH2 = 5
|
||||
local flapsMode = 0
|
||||
local flapsCH1 = 6
|
||||
local flapsCH2 = 7
|
||||
local brakesMode = 0
|
||||
local brakesCH1 = 8
|
||||
local brakesCH2 = 9
|
||||
local tailMode = 1
|
||||
local eleCH1 = 0
|
||||
local eleCH2 = 4
|
||||
local rudCH1 = 0
|
||||
local servoPage = nil
|
||||
|
||||
-- Common functions
|
||||
local lastBlink = 0
|
||||
local function blinkChanged()
|
||||
local time = getTime() % 128
|
||||
local blink = (time - time % 64) / 64
|
||||
if blink ~= lastBlink then
|
||||
lastBlink = blink
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldIncDec(event, value, max, force)
|
||||
if edit or force==true then
|
||||
if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
value = (value + max)
|
||||
dirty = true
|
||||
elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
value = (value + max + 2)
|
||||
dirty = true
|
||||
end
|
||||
value = (value % (max+1))
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function valueIncDec(event, value, min, max)
|
||||
if edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
if value < max then
|
||||
value = (value + 1)
|
||||
dirty = true
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
if value > min then
|
||||
value = (value - 1)
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function navigate(event, fieldMax, prevPage, nextPage)
|
||||
if event == EVT_VIRTUAL_ENTER then
|
||||
edit = not edit
|
||||
dirty = true
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
edit = false
|
||||
dirty = true
|
||||
elseif not dirty then
|
||||
dirty = blinkChanged()
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
page = nextPage
|
||||
field = 0
|
||||
dirty = true
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
||||
page = prevPage
|
||||
field = 0
|
||||
killEvents(event);
|
||||
dirty = true
|
||||
else
|
||||
field = fieldIncDec(event, field, fieldMax, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getFieldFlags(position)
|
||||
flags = 0
|
||||
if field == position then
|
||||
flags = INVERS
|
||||
if edit then
|
||||
flags = INVERS + BLINK
|
||||
end
|
||||
end
|
||||
return flags
|
||||
end
|
||||
|
||||
local function channelIncDec(event, value)
|
||||
if not edit and event==EVT_VIRTUAL_MENU then
|
||||
servoPage = value
|
||||
dirty = true
|
||||
else
|
||||
value = valueIncDec(event, value, 0, 15)
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
-- Init function
|
||||
local function init()
|
||||
rudCH1 = defaultChannel(0)
|
||||
eleCH1 = defaultChannel(1)
|
||||
thrCH1 = defaultChannel(2)
|
||||
ailCH1 = defaultChannel(3)
|
||||
end
|
||||
|
||||
-- Engine Menu
|
||||
local engineModeItems = {"No", "Yes"}
|
||||
local function drawEngineMenu()
|
||||
lcd.clear()
|
||||
if engineMode == 1 then
|
||||
-- 1 channel
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+thrCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
else
|
||||
-- No engine
|
||||
fieldsMax = 0
|
||||
end
|
||||
lcd.drawText(1, 0, "Got an engine?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, engineModeItems, engineMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function engineMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawEngineMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page, page+1)
|
||||
|
||||
if field==0 then
|
||||
engineMode = fieldIncDec(event, engineMode, 1)
|
||||
elseif field==1 then
|
||||
thrCH1 = channelIncDec(event, thrCH1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Ailerons Menu
|
||||
local aileronsModeItems = {"No", "Yes, 1 channel", "Yes, 2 channels"}
|
||||
local function drawAileronsMenu()
|
||||
lcd.clear()
|
||||
if aileronsMode == 2 then
|
||||
-- 2 channels
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(30, 40, "L", 0);
|
||||
lcd.drawText(65, 40, "R", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+ailCH1, getFieldFlags(1))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+ailCH2, getFieldFlags(2))
|
||||
fieldsMax = 2
|
||||
elseif aileronsMode == 1 then
|
||||
-- 1 channel
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+ailCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
else
|
||||
-- No ailerons
|
||||
fieldsMax = 0
|
||||
end
|
||||
lcd.drawText(1, 0, "Got ailerons?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, aileronsModeItems, aileronsMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function aileronsMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawAileronsMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
|
||||
if field==0 then
|
||||
aileronsMode = fieldIncDec(event, aileronsMode, 2)
|
||||
elseif field==1 then
|
||||
ailCH1 = channelIncDec(event, ailCH1)
|
||||
elseif field==2 then
|
||||
ailCH2 = channelIncDec(event, ailCH2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Flaps Menu
|
||||
local flapsModeItems = {"No", "Yes, 1 channel", "Yes, 2 channels"}
|
||||
local function drawFlapsMenu()
|
||||
lcd.clear()
|
||||
if flapsMode == 0 then
|
||||
-- no flaps
|
||||
fieldsMax = 0
|
||||
elseif flapsMode == 1 then
|
||||
-- 1 channel
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+flapsCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
elseif flapsMode == 2 then
|
||||
-- 2 channels
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(30, 40, "L", 0);
|
||||
lcd.drawText(65, 40, "R", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+flapsCH1, getFieldFlags(1))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+flapsCH2, getFieldFlags(2))
|
||||
fieldsMax = 2
|
||||
end
|
||||
lcd.drawText(1, 0, "Got flaps?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, flapsModeItems, flapsMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function flapsMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawFlapsMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
|
||||
if field==0 then
|
||||
flapsMode = fieldIncDec(event, flapsMode, 2)
|
||||
elseif field==1 then
|
||||
flapsCH1 = channelIncDec(event, flapsCH1)
|
||||
elseif field==2 then
|
||||
flapsCH2 = channelIncDec(event, flapsCH2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Airbrakes Menu
|
||||
local brakesModeItems = {"No", "Yes, 1 channel", "Yes, 2 channels"}
|
||||
local function drawBrakesMenu()
|
||||
lcd.clear()
|
||||
if brakesMode == 0 then
|
||||
-- no brakes
|
||||
fieldsMax = 0
|
||||
elseif brakesMode == 1 then
|
||||
-- 1 channel
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+brakesCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
elseif brakesMode == 2 then
|
||||
-- 2 channels
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(30, 40, "L", 0);
|
||||
lcd.drawText(65, 40, "R", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+brakesCH1, getFieldFlags(1))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+brakesCH2, getFieldFlags(2))
|
||||
fieldsMax = 2
|
||||
end
|
||||
lcd.drawText(1, 0, "Got air brakes?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, brakesModeItems, brakesMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function brakesMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawBrakesMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
|
||||
if field==0 then
|
||||
brakesMode = fieldIncDec(event, brakesMode, 2)
|
||||
elseif field==1 then
|
||||
brakesCH1 = channelIncDec(event, brakesCH1)
|
||||
elseif field==2 then
|
||||
brakesCH2 = channelIncDec(event, brakesCH2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Tail Menu
|
||||
local tailModeItems = {"Ele(1)", "Ele(1) + Ruder(1)", "Ele(2) + Ruder(1)", "V-Tail(2)"}
|
||||
local function drawTailMenu()
|
||||
lcd.clear()
|
||||
if tailMode == 0 then
|
||||
-- Elevator(1ch), no rudder...
|
||||
lcd.drawText(5, 30, "Assign channel", 0);
|
||||
lcd.drawText(5, 40, ">>>", 0);
|
||||
lcd.drawSource(25, 40, MIXSRC_CH1+eleCH1, getFieldFlags(1))
|
||||
fieldsMax = 1
|
||||
elseif tailMode == 1 then
|
||||
-- Elevator(1ch) + rudder...
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(25, 40, "Ele", 0);
|
||||
lcd.drawText(60, 40, "Rud", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+eleCH1, getFieldFlags(1))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+rudCH1, getFieldFlags(2))
|
||||
fieldsMax = 2
|
||||
elseif tailMode == 2 then
|
||||
-- Elevator(2ch) + rudder...
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(25, 40, "EleL", 0);
|
||||
lcd.drawText(60, 40, "EleR", 0);
|
||||
lcd.drawText(95, 40, "Rud", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+eleCH1, getFieldFlags(1))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+eleCH2, getFieldFlags(2))
|
||||
lcd.drawSource(95, 50, MIXSRC_CH1+rudCH1, getFieldFlags(3))
|
||||
fieldsMax = 3
|
||||
else
|
||||
-- V-Tail...
|
||||
lcd.drawText(5, 30, "Assign channels", 0);
|
||||
lcd.drawText(25, 40, "VtaL", 0);
|
||||
lcd.drawText(60, 40, "VtaR", 0);
|
||||
lcd.drawText(5, 50, ">>>", 0);
|
||||
lcd.drawSource(25, 50, MIXSRC_CH1+eleCH1, getFieldFlags(1))
|
||||
lcd.drawSource(60, 50, MIXSRC_CH1+eleCH2, getFieldFlags(2))
|
||||
fieldsMax = 2
|
||||
end
|
||||
lcd.drawText(1, 0, "Tail config", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawCombobox(0, 8, LCD_W, tailModeItems, tailMode, getFieldFlags(0))
|
||||
end
|
||||
|
||||
local function tailMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawTailMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page-1, page+1)
|
||||
|
||||
if field==0 then
|
||||
tailMode = fieldIncDec(event, tailMode, 3)
|
||||
elseif field==1 then
|
||||
eleCH1 = channelIncDec(event, eleCH1)
|
||||
elseif (field==2 and tailMode==1) or field==3 then
|
||||
rudCH1 = channelIncDec(event, rudCH1)
|
||||
elseif field==2 then
|
||||
eleCH2 = channelIncDec(event, eleCH2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Servo (limits) Menu
|
||||
local function drawServoMenu(limits)
|
||||
lcd.clear()
|
||||
lcd.drawSource(1, 0, MIXSRC_CH1+servoPage, 0)
|
||||
lcd.drawText(25, 0, "servo min/max/center/direction?", 0)
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 8, FILL_WHITE)
|
||||
lcd.drawLine(LCD_W/2-1, 8, LCD_W/2-1, LCD_H, DOTTED, 0)
|
||||
lcd.drawText(LCD_W/2-19, LCD_H-8, ">>>", 0);
|
||||
lcd.drawNumber(140, 35, limits.min, PREC1+getFieldFlags(0));
|
||||
lcd.drawNumber(205, 35, limits.max, PREC1+getFieldFlags(1));
|
||||
lcd.drawNumber(170, 9, limits.offset, PREC1+getFieldFlags(2));
|
||||
if limits.revert == 0 then
|
||||
lcd.drawText(129, 50, "\126", getFieldFlags(3));
|
||||
else
|
||||
lcd.drawText(129, 50, "\127", getFieldFlags(3));
|
||||
end
|
||||
fieldsMax = 3
|
||||
end
|
||||
|
||||
local function servoMenu(event)
|
||||
local limits = model.getOutput(servoPage)
|
||||
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawServoMenu(limits)
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, page, page)
|
||||
|
||||
if edit then
|
||||
if field==0 then
|
||||
limits.min = valueIncDec(event, limits.min, -1000, 0)
|
||||
elseif field==1 then
|
||||
limits.max = valueIncDec(event, limits.max, 0, 1000)
|
||||
elseif field==2 then
|
||||
limits.offset = valueIncDec(event, limits.offset, -1000, 1000)
|
||||
elseif field==3 then
|
||||
limits.revert = fieldIncDec(event, limits.revert, 1)
|
||||
end
|
||||
model.setOutput(servoPage, limits)
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
servoPage = nil
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Confirmation Menu
|
||||
local function drawNextLine(x, y, label, channel)
|
||||
lcd.drawText(x, y, label, 0);
|
||||
lcd.drawText(x+26, y, ":", 0);
|
||||
lcd.drawSource(x+30, y, MIXSRC_CH1+channel, 0)
|
||||
y = y + 8
|
||||
if y > 50 then
|
||||
y = 12
|
||||
x = 70
|
||||
end
|
||||
return x, y
|
||||
end
|
||||
|
||||
local function drawConfirmationMenu()
|
||||
local x = 5
|
||||
local y = 12
|
||||
lcd.clear()
|
||||
lcd.drawText(0, 1, "Ready to go?", 0);
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 9, 0)
|
||||
if engineMode == 1 then
|
||||
x, y = drawNextLine(x, y, "Thr", thrCH1)
|
||||
end
|
||||
if aileronsMode == 1 then
|
||||
x, y = drawNextLine(x, y, "Ail", ailCH1)
|
||||
elseif aileronsMode == 2 then
|
||||
x, y = drawNextLine(x, y, "AilL", ailCH1)
|
||||
x, y = drawNextLine(x, y, "AilR", ailCH2)
|
||||
end
|
||||
if flapsMode == 1 then
|
||||
x, y = drawNextLine(x, y, "Flap", flapsCH1)
|
||||
elseif flapsMode == 2 then
|
||||
x, y = drawNextLine(x, y, "FlpL", flapsCH1)
|
||||
x, y = drawNextLine(x, y, "FlpR", flapsCH2)
|
||||
end
|
||||
if brakesMode == 1 then
|
||||
x, y = drawNextLine(x, y, "Brak", brakesCH1)
|
||||
elseif brakesMode == 2 then
|
||||
x, y = drawNextLine(x, y, "BrkL", brakesCH1)
|
||||
x, y = drawNextLine(x, y, "BrkR", brakesCH2)
|
||||
end
|
||||
if tailMode == 3 then
|
||||
x, y = drawNextLine(x, y, "VtaL", eleCH1)
|
||||
x, y = drawNextLine(x, y, "VtaR", eleCH2)
|
||||
else
|
||||
x, y = drawNextLine(x, y, "Rud", rudCH1)
|
||||
if tailMode == 1 then
|
||||
x, y = drawNextLine(x, y, "Elev", eleCH1)
|
||||
elseif tailMode == 2 then
|
||||
x, y = drawNextLine(x, y, "EleL", eleCH1)
|
||||
x, y = drawNextLine(x, y, "EleR", eleCH2)
|
||||
end
|
||||
end
|
||||
lcd.drawText(0, LCD_H-8, "[Enter Long] to confirm", 0);
|
||||
lcd.drawFilledRectangle(0, LCD_H-9, LCD_W, 9, 0)
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function addMix(channel, input, name, weight, index)
|
||||
local mix = { source=input, name=name }
|
||||
if weight ~= nil then
|
||||
mix.weight = weight
|
||||
end
|
||||
if index == nil then
|
||||
index = 0
|
||||
end
|
||||
model.insertMix(channel, index, mix)
|
||||
end
|
||||
|
||||
local function applySettings()
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
if engineMode > 0 then
|
||||
addMix(thrCH1, MIXSRC_FIRST_INPUT+defaultChannel(2), "Engine")
|
||||
end
|
||||
if aileronsMode == 1 then
|
||||
addMix(ailCH1, MIXSRC_FIRST_INPUT+defaultChannel(3), "Ail")
|
||||
elseif aileronsMode == 2 then
|
||||
addMix(ailCH1, MIXSRC_FIRST_INPUT+defaultChannel(3), "AilL", -100)
|
||||
addMix(ailCH2, MIXSRC_FIRST_INPUT+defaultChannel(3), "AilR")
|
||||
end
|
||||
if flapsMode == 1 then
|
||||
addMix(flapsCH1, MIXSRC_SA, "Flap")
|
||||
elseif flapsMode == 2 then
|
||||
addMix(flapsCH1, MIXSRC_SA, "FlapL")
|
||||
addMix(flapsCH2, MIXSRC_SA, "FlapR")
|
||||
end
|
||||
if brakesMode == 1 then
|
||||
addMix(brakesCH1, MIXSRC_SD, "Brake")
|
||||
elseif brakesMode == 2 then
|
||||
addMix(brakesCH1, MIXSRC_SD, "BrakeL")
|
||||
addMix(brakesCH2, MIXSRC_SD, "BrakeR")
|
||||
end
|
||||
if tailMode == 3 then
|
||||
addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "V-EleL", 50)
|
||||
addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(0), "V-RudL", -50, 1)
|
||||
addMix(eleCH2, MIXSRC_FIRST_INPUT+defaultChannel(1), "V-EleR", 50)
|
||||
addMix(eleCH2, MIXSRC_FIRST_INPUT+defaultChannel(0), "V-RudR", 50, 1)
|
||||
else
|
||||
if tailMode > 0 then
|
||||
addMix(rudCH1, MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder")
|
||||
end
|
||||
if tailMode == 1 then
|
||||
addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "Elev")
|
||||
elseif tailMode == 2 then
|
||||
addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "ElevG")
|
||||
addMix(eleCH2, MIXSRC_FIRST_INPUT+defaultChannel(1), "ElevD")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function confirmationMenu(event)
|
||||
if dirty then
|
||||
dirty = false
|
||||
drawConfirmationMenu()
|
||||
end
|
||||
|
||||
navigate(event, fieldsMax, TAIL_PAGE, page)
|
||||
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER_LONG then
|
||||
killEvents(event)
|
||||
applySettings()
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
end
|
||||
|
||||
if servoPage ~= nil then
|
||||
servoMenu(event)
|
||||
elseif page == ENGINE_PAGE then
|
||||
engineMenu(event)
|
||||
elseif page == AILERONS_PAGE then
|
||||
aileronsMenu(event)
|
||||
elseif page == FLAPERONS_PAGE then
|
||||
flapsMenu(event)
|
||||
elseif page == BRAKES_PAGE then
|
||||
brakesMenu(event)
|
||||
elseif page == TAIL_PAGE then
|
||||
tailMenu(event)
|
||||
elseif page == CONFIRMATION_PAGE then
|
||||
return confirmationMenu(event)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
87
SCRIPTS/WIZARD/wizard.lua
Executable file
87
SCRIPTS/WIZARD/wizard.lua
Executable file
|
|
@ -0,0 +1,87 @@
|
|||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) EdgeTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
-- Model types
|
||||
local modelType = 0
|
||||
local MODELTYPE_PLANE = 0
|
||||
local MODELTYPE_DELTA = 1
|
||||
local MODELTYPE_QUAD = 2
|
||||
local MODELTYPE_HELI = 3
|
||||
-- Common functions
|
||||
local function fieldIncDec(event, value, max)
|
||||
if event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
value = (value - 1)
|
||||
elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
value = (value + max + 3)
|
||||
end
|
||||
value = (value % (max+2))
|
||||
return value
|
||||
end
|
||||
|
||||
-- Model Type Menu
|
||||
local function modelTypeSurround(index)
|
||||
if index <= 1 then
|
||||
lcd.drawFilledRectangle(59*(index%2)+12, 13, 43, 23)
|
||||
else
|
||||
lcd.drawFilledRectangle(59*(index%2)+12, 34, 40, 20)
|
||||
end
|
||||
end
|
||||
|
||||
local function drawModelChoiceMenu()
|
||||
lcd.clear()
|
||||
lcd.drawScreenTitle("Select model type", 0, 0)
|
||||
lcd.drawText( 20, 20, "Plane")
|
||||
lcd.drawText( 78, 20, "Delta")
|
||||
lcd.drawText( 20, 40, "Multi")
|
||||
lcd.drawText( 78, 40, "Heli")
|
||||
modelTypeSurround(modelType)
|
||||
fieldsMax = 0
|
||||
end
|
||||
|
||||
local function modelTypeMenu(event)
|
||||
drawModelChoiceMenu()
|
||||
if event == EVT_VIRTUAL_ENTER then
|
||||
if modelType == MODELTYPE_PLANE then
|
||||
return "plane.lua"
|
||||
elseif modelType == MODELTYPE_DELTA then
|
||||
return "delta.lua"
|
||||
elseif modelType == MODELTYPE_QUAD then
|
||||
return "multi.lua"
|
||||
elseif modelType == MODELTYPE_HELI then
|
||||
return "heli.lua"
|
||||
end
|
||||
else
|
||||
modelType = fieldIncDec(event, modelType, 2)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
end
|
||||
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
end
|
||||
|
||||
|
||||
return modelTypeMenu(event)
|
||||
end
|
||||
|
||||
return { run=run }
|
||||
BIN
SCRIPTS/WIZARD/wizard.luac
Executable file
BIN
SCRIPTS/WIZARD/wizard.luac
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue