From 7cd7869d6afb929ccd49bbdc796dfac4bd9121f1 Mon Sep 17 00:00:00 2001 From: NiklasVoigt Date: Sat, 9 Sep 2017 13:47:05 +0200 Subject: [PATCH] Taranis Q X7 optimized wizard (#5198) * Redesigned Wizard for the X7 Check this out: https://www.youtube.com/watch?v=86H1YKcVyB4 * Removed the developers name * Rendering issue fix * Removed bottom bar & removed Heli uncommented Heli for easier implementing in the future --- .../taranis-x7/SCRIPTS/WIZARD/delta.lua | 366 ++++++++++++ .../taranis-x7/SCRIPTS/WIZARD/multi.lua | 292 +++++++++ .../taranis-x7/SCRIPTS/WIZARD/plane.lua | 561 ++++++++++++++++++ .../taranis-x7/SCRIPTS/WIZARD/wizard.lua | 79 +++ 4 files changed, 1298 insertions(+) create mode 100755 radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua create mode 100755 radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua create mode 100755 radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua create mode 100755 radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua new file mode 100755 index 000000000..d88c04b7b --- /dev/null +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/delta.lua @@ -0,0 +1,366 @@ +-- 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_ROT_RIGHT then + value = (value + max) + dirty = true + elseif event == EVT_ROT_LEFT 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_ROT_RIGHT or event == EVT_ROT_RIGHT then + if value < max then + value = (value + 1) + dirty = true + end + elseif event == EVT_ROT_LEFT or event == EVT_ROT_LEFT 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_ENTER_BREAK then + edit = not edit + dirty = true + elseif edit then + if event == EVT_EXIT_BREAK then + edit = false + dirty = true + elseif not dirty then + dirty = blinkChanged() + end + else + if event == EVT_PAGE_BREAK then + page = nextPage + field = 0 + dirty = true + elseif event == EVT_PAGE_LONG 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_MENU_BREAK 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_EXIT_BREAK 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), "Elev1-E", 50) + addMix(elevCH1, MIXSRC_FIRST_INPUT+defaultChannel(3), "Elev1-A", 50, 1) + addMix(elevCH2, MIXSRC_FIRST_INPUT+defaultChannel(1), "Elev2-E", 50) + addMix(elevCH2, MIXSRC_FIRST_INPUT+defaultChannel(3), "Elev2-A", -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.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, "Elevons:", elevCH1) + x, y = drawNextLine(x, y, "Elevons:", elevCH2) + if rudderMode == 1 then + drawNextLine(x, y, "Rudder:", rudCH1) + end + lcd.drawText(48, 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_EXIT_BREAK then + return 2 + elseif event == EVT_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 } diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua new file mode 100755 index 000000000..17c3b3414 --- /dev/null +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/multi.lua @@ -0,0 +1,292 @@ +-- Multicopter Wizard pages +local THROTTLE_PAGE = 0 +local ROLL_PAGE = 1 +local PITCH_PAGE = 2 +local YAW_PAGE = 3 +local CONFIRMATION_PAGE = 4 + +-- Navigation variables +local page = THROTTLE_PAGE +local dirty = true +local edit = false +local field = 0 +local fieldsMax = 0 +local comboBoxMode = 0 -- Scrap variable + +-- Model settings +local thrCH1 = 0 +local rollCH1 = 0 +local yawCH1 = 0 +local pitchCH1 = 0 + +-- 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_ROT_RIGHT then + value = (value + max) + dirty = true + elseif event == EVT_ROT_LEFT 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_ROT_RIGHT or event == EVT_ROT_RIGHT then + if value < max then + value = (value + 1) + dirty = true + end + elseif event == EVT_ROT_LEFT or event == EVT_ROT_LEFT 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_ENTER_BREAK then + edit = not edit + dirty = true + elseif edit then + if event == EVT_EXIT_BREAK then + edit = false + dirty = true + elseif not dirty then + dirty = blinkChanged() + end + else + if event == EVT_PAGE_BREAK then + page = nextPage + field = 0 + dirty = true + elseif event == EVT_PAGE_LONG 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_MENU_BREAK then + servoPage = value + dirty = true + else + value = valueIncDec(event, value, 0, 15) + end + return value +end + +-- Init function +local function init() + thrCH1 = defaultChannel(2) + rollCH1 = defaultChannel(3) + yawCH1 = defaultChannel(0) + pitchCH1 = defaultChannel(1) +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 + +-- Confirmation Menu +local function drawNextLine(x, y, label, channel) + lcd.drawText(x, y, label, 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(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) + 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") +end + +local function confirmationMenu(event) + if dirty then + dirty = false + drawConfirmationMenu() + end + + navigate(event, fieldsMax, YAW_PAGE, page) + + if event == EVT_EXIT_BREAK then + return 2 + elseif event == EVT_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 == CONFIRMATION_PAGE then + return confirmationMenu(event) + end + return 0 +end + +return { init=init, run=run } diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua new file mode 100755 index 000000000..d39a1454c --- /dev/null +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/plane.lua @@ -0,0 +1,561 @@ +-- 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 = 4 +local flapsMode = 0 +local flapsCH1 = 5 +local flapsCH2 = 6 +local brakesMode = 0 +local brakesCH1 = 8 +local brakesCH2 = 9 +local tailMode = 1 +local eleCH1 = 0 +local eleCH2 = 7 +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_ROT_LEFT then + value = (value + max) + dirty = true + elseif event == EVT_ROT_RIGHT 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_ROT_LEFT or event == EVT_ROT_LEFT then + if value < max then + value = (value + 1) + dirty = true + end + elseif event == EVT_ROT_RIGHT or event == EVT_ROT_RIGHT 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_ENTER_BREAK then + edit = not edit + dirty = true + elseif edit then + if event == EVT_EXIT_BREAK then + edit = false + dirty = true + elseif not dirty then + dirty = blinkChanged() + end + else + if event == EVT_PAGE_BREAK then + page = nextPage + field = 0 + dirty = true + elseif event == EVT_PAGE_LONG 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_MENU_BREAK 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", "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", "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", "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(1ch), no Ruder", "Ele(1ch) + Ruder", "Ele(2ch) + Ruder", "V-Tail"} +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, "Ele", 0); + lcd.drawText(60, 40, "Ele", 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, "Vta", 0); + lcd.drawText(60, 40, "Vta", 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_EXIT_BREAK then + servoPage = nil + dirty = true + end +end + +-- Confirmation Menu +local function drawNextLine(x, y, label, channel) + lcd.drawText(x, y, label, 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, "Thro:", thrCH1) + end + if aileronsMode > 0 then + x, y = drawNextLine(x, y, "Aile:", ailCH1) + if aileronsMode == 2 then + x, y = drawNextLine(x, y, "Aile:", ailCH2) + end + end + if flapsMode > 0 then + x, y = drawNextLine(x, y, "Flap:", flapsCH1) + if flapsMode == 2 then + x, y = drawNextLine(x, y, "Flap:", flapsCH2) + end + end + if brakesMode > 0 then + x, y = drawNextLine(x, y, "Brak:", brakesCH1) + if brakesMode == 2 then + x, y = drawNextLine(x, y, "Brak:", brakesCH2) + end + end + if tailMode == 3 then + x, y = drawNextLine(x, y, "V-Ta:", eleCH1) + x, y = drawNextLine(x, y, "V-Ta:", eleCH2) + else + x, y = drawNextLine(x, y, "Elev:", eleCH1) + if tailMode == 2 then + x, y = drawNextLine(x, y, "Elev:", eleCH2) + end + drawNextLine(x, y, "Rudd:", 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 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 > 0 then + addMix(ailCH1, MIXSRC_FIRST_INPUT+defaultChannel(3), "Aileron") + if aileronsMode == 2 then + addMix(ailCH2, MIXSRC_FIRST_INPUT+defaultChannel(3), "Aileron", -100) + end + end + if flapsMode > 0 then + addMix(flapsCH1, MIXSRC_SA, "Flap") + if flapsMode == 2 then + addMix(flapsCH2, MIXSRC_SA, "Flap") + end + end + if brakesMode > 0 then + addMix(brakesCH1, MIXSRC_SE, "Brake") + if brakesMode == 2 then + addMix(brakesCH2, MIXSRC_SE, "Brake") + end + end + if tailMode == 3 then + addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "V-Tail-E", 50) + addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(0), "V-Tail-R", 50, 1) + addMix(eleCH2, MIXSRC_FIRST_INPUT+defaultChannel(1), "V-Tail-E", 50) + addMix(eleCH2, MIXSRC_FIRST_INPUT+defaultChannel(0), "V-Tail-R", -50, 1) + else + addMix(eleCH1, MIXSRC_FIRST_INPUT+defaultChannel(1), "Elevator") + if tailMode > 0 then + addMix(rudCH1, MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder") + end + if tailMode == 2 then + addMix(eleCH2, MIXSRC_FIRST_INPUT+defaultChannel(1), "Elevator") + end + end +end + +local function confirmationMenu(event) + if dirty then + dirty = false + drawConfirmationMenu() + end + + navigate(event, fieldsMax, TAIL_PAGE, page) + + if event == EVT_EXIT_BREAK then + return 2 + elseif event == EVT_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 } diff --git a/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua new file mode 100755 index 000000000..c0ab1df0c --- /dev/null +++ b/radio/sdcard/taranis-x7/SCRIPTS/WIZARD/wizard.lua @@ -0,0 +1,79 @@ +-- Navigation variables +local dirty = true + +-- Model types +local modelType = 0 +local MODELTYPE_PLANE = 0 +-- local MODELTYPE_HELI = 1 -- change order for implementing Heli +local MODELTYPE_DELTA = 1 +local MODELTYPE_QUAD = 2 + +-- Common functions +local function fieldIncDec(event, value, max) + if event == EVT_ROT_LEFT then + value = (value + max) + dirty = true + elseif event == EVT_ROT_RIGHT then + value = (value + max + 2) + dirty = true + end + value = (value % (max+1)) + 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) + if dirty == true then + drawModelChoiceMenu() + dirty = false + end + if event == EVT_ENTER_BREAK then + if modelType == MODELTYPE_PLANE then + return "plane.lua" + -- elseif modelType == MODELTYPE_HELI then + elseif modelType == MODELTYPE_DELTA then + return "delta.lua" + elseif modelType == MODELTYPE_QUAD then + return "multi.lua" + end + dirty = true + else + modelType = fieldIncDec(event, modelType, 2) -- 3 for implementing Heli + 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_EXIT_BREAK then + return 2 + end + + + return modelTypeMenu(event) +end + +return { run=run }