DIY-Multiprotocol-TX-Module/Lua_scripts/DSM FwdPrg_56_STUP.lua

952 lines
30 KiB
Lua
Raw Normal View History

local toolName = "TNS|DSM Frwd Prog v0.56a (MIN-SETUP)|TNE"
---- #########################################################################
---- # #
---- # 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. #
---- # #
---- #########################################################################
local VERSION = "v0.56"
local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/"
local DATA_PATH = "/MODELS/DSMDATA"
local LOG_FILE = "/LOGS/dsm_min_log.txt"
-- Phase
local PH_INIT = 0
local PH_RX_VER, PH_TITLE = 1, 2
local PH_VAL_CHANGING, PH_VAL_EDITING, PH_VAL_EDIT_END = 6, 7, 8
local PH_WAIT_CMD, PH_EXIT_REQ, PH_EXIT_DONE = 9, 10, 11
-- Line Types
local LT_MENU, LT_LIST_NC = 0x1C, 0x6C
local Phase = PH_INIT
local Text = {}
local List_Text = {}
local List_Text_Img = {}
local originalValue = 0
local ctx_SelLine = 0 -- Current Selected Line
local ctx_EditLine = nil -- Current Editing Line
local Menu = { MenuId = 0, Text = "", TextId = 0, PrevId = 0, NextId = 0, BackId = 0 }
local MenuLines = {}
local logFile = nil
local LCD_W_BUTTONS = 19
local LCD_H_BUTTONS = 10
local LCD_X_MAX = 128
local LCD_X_RIGHT_BUTTONS = LCD_X_MAX - LCD_W_BUTTONS - 1
local LCD_Y_LINE_HEIGHT = 7
local LCD_Y_LOWER_BUTTONS = (8 * LCD_Y_LINE_HEIGHT) + 2
local TEXT_ATTR = SMLSIZE
local TX_CHANNELS = 12
local AT_PLANE = 0
local aircraft_type_text = {[0]="Plane","Heli","Glider","Drone"}
local WT_A1 = 0
local WT_A2 = 1
local WT_FLPR = 2
local WT_A1_F1 = 3
local WT_A2_F1 = 4
local WT_A2_F2 = 5
local WT_ELEVON_A = 6
local WT_ELEVON_B = 7
local wing_type_text = {[0]="Normal","Dual Ail","Flapperon", "Ail + Flp","Dual Ail + Flp","Dual Ail/Flp","Elevon A","Elevon B"}
local TT_R1 = 0
local TT_R1_E1 = 1
local TT_R1_E2 = 2
local TT_R2_E1 = 3
local TT_R2_E2 = 4
local TT_VT_A = 5
local TT_VT_B = 6
local TT_TLRN_A = 7
local TT_TLRN_B = 8
local TT_TLRN_A_R2 = 9
local TT_TLRN_B_R2 = 10
local tail_type_text = {[0]="Rud Only","Normal","Rud + Dual Ele","Dual Rud + Elv","Dual Rud/Ele",
"VTail A","VTail B","Taileron A","Taileron B",
"Taileron A + Dual Rud","Taileron B + Dual Rud"
}
local MT_NORMAL = 0
local MT_REVERSE = 1
local P1 = 0
local P2 = 1
local P3 = 2
local P4 = 3
local P5 = 4
local P6 = 5
local P7 = 6
local P8 = 7
--local P9 = 8
--local P10 = 9
local MV_AIRCRAFT_TYPE = 1001
local MV_WING_TYPE = 1002
local MV_TAIL_TYPE = 1003
local MV_CH_BASE = 1010
local MV_CH_THR = 1010
local MV_CH_L_AIL = 1011
local MV_CH_R_AIL = 1012
local MV_CH_L_FLP = 1013
local MV_CH_R_FLP = 1014
local MV_CH_L_RUD = 1015
local MV_CH_R_RUD = 1016
local MV_CH_L_ELE = 1017
local MV_CH_R_ELE = 1018
local MV_PORT_BASE = 1020
local MV_P1_MODE = 1020
--local MV_P2_MODE = 1021
--local MV_P3_MODE = 1022
--local MV_P4_MODE = 1023
--local MV_P5_MODE = 1024
local MV_P6_MODE = 1025
--local MV_P7_MODE = 1026
--local MV_P8_MODE = 1027
--local MV_P9_MODE = 1028
--local MV_P10_MODE = 1029
local MV_DATA_END = 1040
-- MENU DATA Management
local M_DB = {} -- Store the variables used in the Menus.
local lastGoodMenu=0
local currATyp = -1
local currTTyp = -1
local currWTyp = -1
local menuDataChanged = false
local MODEL = {
modelName = "", -- The name of the model comming from OTX/ETX
hashName = nil,
modelOutputChannel = {}, -- Output information from OTX/ETX
TX_CH_TEXT= { },
PORT_TEXT = { },
DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script
}
local function gc()
collectgarbage("collect")
end
--[[
local function gcTable(t)
if type(t)=="table" then
for i,v in pairs(t) do
if type(v) == "table" then
gcTable(v)
end
t[i] = nil
end
end
gc()
return t
end
--]]
local function LOG_open()
logFile = io.open(LOG_FILE, "w") -- Truncate Log File
end
local function LOG_write(...)
if (logFile == nil) then LOG_open() end
local str = string.format(...)
io.write(logFile, str)
end
local function LOG_close()
if (logFile ~= nil) then io.close(logFile) end
end
-- Saves MENU_DATA to a file
local function ST_SaveFileData()
local fname = MODEL.hashName
print("Saving File:"..fname)
local dataFile = assert(io.open(DATA_PATH .. "/" .. fname, "w"),"Please create "..DATA_PATH.." folder") -- write File
-- Foreach MENU_DATA with a value write Var_Id:Value into file
for i = 0, MV_DATA_END do
if (M_DB[i]~=nil) then
io.write(dataFile,string.format("%s:%s\n",i,M_DB[i]))
end
end
io.close(dataFile)
end
local function tailTypeCompatible(a,b)
local function normalize(tt)
if (tt==TT_TLRN_A or tt==TT_TLRN_B) then
return TT_TLRN_A
elseif (tt==TT_TLRN_A_R2 or tt==TT_TLRN_B_R2) then
return TT_TLRN_A_R2
elseif (tt==TT_VT_A or tt==TT_VT_B) then
return TT_VT_A
else
return tt
end
end
return (normalize(a)==normalize(b))
end
local function ST_PlaneWingInit(wingType)
--print("Change Plane WingType:"..wing_type_text[wingType])
M_DB[MV_WING_TYPE] = wingType
-- Clear all Wing Data
M_DB[MV_CH_L_AIL] = nil
M_DB[MV_CH_R_AIL] = nil
M_DB[MV_CH_L_FLP] = nil
M_DB[MV_CH_R_FLP] = nil
M_DB[MV_CH_THR] = P1
-- Default Channel Assisgments for each Wing type
if (wingType==WT_A1) then
M_DB[MV_CH_L_AIL] = P2
elseif (wingType==WT_A2 or wingType==WT_FLPR) then
M_DB[MV_CH_L_AIL] = P6
M_DB[MV_CH_R_AIL] = P2
elseif (wingType==WT_A1_F1) then
M_DB[MV_CH_L_AIL] = P2
M_DB[MV_CH_L_FLP] = P6
elseif (wingType==WT_A2_F1) then
M_DB[MV_CH_L_AIL] = P6
M_DB[MV_CH_R_AIL] = P2
M_DB[MV_CH_L_FLP] = P5
elseif (wingType==WT_A2_F2) then
M_DB[MV_CH_L_AIL] = P6
M_DB[MV_CH_R_AIL] = P2
M_DB[MV_CH_R_FLP] = P5
M_DB[MV_CH_L_FLP] = P7
elseif (wingType==WT_ELEVON_A) then
M_DB[MV_CH_L_AIL] = P2
M_DB[MV_CH_R_AIL] = P3
elseif (wingType==WT_ELEVON_B) then
M_DB[MV_CH_L_AIL] = P3
M_DB[MV_CH_R_AIL] = P2
else -- Assume normal
print("ERROR: Invalid Wing Type")
end
end
local function ST_PlaneTailInit(tailType)
if (M_DB[MV_WING_TYPE]==WT_ELEVON_A or
M_DB[MV_WING_TYPE]==WT_ELEVON_B) then
tailType = TT_R1 -- Delta only have ruder
end
--print("Change Plane Tail Type:"..tail_type_text[tailType])
-- Clear all data for Tail
M_DB[MV_TAIL_TYPE] = tailType
M_DB[MV_CH_L_ELE] = nil
M_DB[MV_CH_R_ELE] = nil
M_DB[MV_CH_L_RUD] = nil
M_DB[MV_CH_R_RUD] = nil
-- Setup Channels for different Tail types
if (tailType == TT_R1) then
M_DB[MV_CH_L_RUD] = P4
elseif (tailType == TT_R1_E1) then
M_DB[MV_CH_L_ELE] = P3
M_DB[MV_CH_L_RUD] = P4
elseif (tailType == TT_R1_E2) then
M_DB[MV_CH_L_ELE] = P5
M_DB[MV_CH_R_ELE] = P3
M_DB[MV_CH_L_RUD] = P4
elseif (tailType == TT_R2_E1) then
M_DB[MV_CH_L_ELE] = P3
M_DB[MV_CH_L_RUD] = P4
M_DB[MV_CH_R_RUD] = P5
elseif (tailType == TT_R2_E2) then
M_DB[MV_CH_L_ELE] = P5
M_DB[MV_CH_R_ELE] = P3
M_DB[MV_CH_L_RUD] = P4
M_DB[MV_CH_R_RUD] = P6
elseif (tailType == TT_VT_A or tailType == TT_VT_B) then
M_DB[MV_CH_L_ELE] = P3
M_DB[MV_CH_R_ELE] = P4
elseif (tailType == TT_TLRN_A or tailType == TT_TLRN_B or
tailType == TT_TLRN_A_R2 or tailType == TT_TLRN_B_R2) then
M_DB[MV_CH_L_RUD] = P4
M_DB[MV_CH_L_ELE] = P5
M_DB[MV_CH_R_ELE] = P3
else -- Assume Normal
print("ERROR:invalid Tail Type")
end
if (tailType == TT_TLRN_A_R2 or tailType == TT_TLRN_B_R2) then
M_DB[MV_CH_R_RUD] = P8
end
end
local function ST_AircraftInit(aircraftType)
M_DB[MV_AIRCRAFT_TYPE] = aircraftType
ST_PlaneWingInit(WT_A1)
ST_PlaneTailInit(TT_R1_E1)
end
-- Setup Initial Default Data for the Menus
local function ST_Default_Data()
ST_AircraftInit(AT_PLANE)
for i=0,9 do
M_DB[MV_P1_MODE+i] = MT_NORMAL + MODEL.modelOutputChannel[P1+i].revert
end
end
local function MenuLinePostProcessing(line)
line.MenuId = Menu.MenuId
if line.Type == LT_MENU then
-- nothing to do on menu entries
line.Val=nil
elseif line.Type == LT_LIST_NC then
-- Normalize Min/Max to be relative to Zero
line.TextStart = line.Min
line.Def = line.Def - line.Min -- normalize default value
line.Max = line.Max - line.Min -- normalize max index
line.Min = 0 -- min index
end
end
local function portUse(p)
local out = nil
if p==M_DB[MV_CH_THR] then out = "Thr"
elseif p == M_DB[MV_CH_L_AIL] then
out=(M_DB[MV_CH_R_AIL] and "Ail_L") or "Ail"
elseif p == M_DB[MV_CH_R_AIL] then out="Ail_R"
elseif p == M_DB[MV_CH_L_ELE] then
out=(M_DB[MV_CH_R_ELE] and "Ele_L") or "Ele"
elseif p == M_DB[MV_CH_R_ELE] then out="Ele_R"
elseif p == M_DB[MV_CH_L_RUD] then
out=(M_DB[MV_CH_R_RUD] and "Rud_L") or "Rud"
elseif p == M_DB[MV_CH_R_RUD] then out="Rud-R"
elseif p == M_DB[MV_CH_L_FLP] then
out=(M_DB[MV_CH_R_FLP] and "Flp_L") or "Flp"
elseif p == M_DB[MV_CH_R_FLP] then out="Flp_R"
else
out = ""
end
return out
end
-- Creates the menus to Render with the GUI
local function ST_LoadMenu(menuId)
local function Header(p)
return MODEL.PORT_TEXT[p].." "..portUse(p)
end
local function generateGyroReverse(menuId, P_BASE, V_BASE)
for i=0,4 do
MenuLines[i] = { Type = LT_LIST_NC, Text=Header(P_BASE+i), TextId = 0, ValId = V_BASE+i, Min=45, Max=46, Def=45, Val=M_DB[V_BASE+i] }
end
MenuLines[5] = { Type = LT_MENU, Text="Only TAER affects AS3X/SAFE react dir", TextId = 0, ValId = menuId }
MenuLines[6] = { Type = LT_MENU, Text="If changes, RX 'Relearn Servo'", TextId = 0, ValId = menuId }
ctx_SelLine = 0
end
-- Begin
for i = 0, 6 do -- clear menu
MenuLines[i] = { MenuId = 0, lineNum = 0, Type = 0 }
end
if (menuId==0x1000) then -- MAIN MENU
Menu = { MenuId = 0x1000, Text = "Save-Exit ("..MODEL.modelName..")", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
if (true) then
MenuLines[4] = { Type = LT_MENU, Text="Save Changes", TextId = 0, ValId = 0x1005 }
MenuLines[5] = { Type = LT_MENU, Text="Discard Changes", TextId = 0, ValId = 0xFFF9 }
ctx_SelLine = 4
end
lastGoodMenu = menuId
elseif (menuId==0x1001) then -- MODEL SETUP
local backId = 0xFFF9 -- No changes, just exit
local title = "Setup ("..MODEL.modelName..")"
if (menuDataChanged) then
backId = 0x1000 -- Go to Save menu
title = title.." *"
end
Menu = { MenuId = 0x1001, Text = title, PrevId = 0, NextId = 0, BackId = backId, TextId=0 }
MenuLines[0] = { Type = LT_MENU, Text = "Aircraft Setup", ValId = 0x1010,TextId=0 }
MenuLines[1] = { Type = LT_MENU, Text = "Wing & Tail Channels ", ValId = 0x1020, TextId=0 }
MenuLines[3] = { Type = LT_MENU, Text = "Gyro Channel Reverse", ValId = 0x1030, TextId=0 }
MenuLines[5] = { Type = LT_MENU, Text = "WARNING: Changing of Aircraft", ValId = 0x1001, TextId=0 }
MenuLines[6] = { Type = LT_MENU, Text = "deletes prev Ch/Port assgmt.", ValId = 0x1001, TextId=0 }
ctx_SelLine = 0
lastGoodMenu = menuId
elseif (menuId==0x1005) then
ST_SaveFileData()
menuDataChanged = false
local msg1 = "Data saved to: "
local msg2 = " ../DSMLIB/"..MODEL.hashName
Menu = { MenuId = 0x1005, Text = "Config Saved", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
MenuLines[2] = { Type = LT_MENU, Text=msg1, TextId = 0, ValId = 0x1005 }
MenuLines[3] = { Type = LT_MENU, Text=msg2, TextId = 0, ValId = 0x1005 }
MenuLines[6] = { Type = LT_MENU, Text="Complete", TextId = 0, ValId = 0xFFF9 }
ctx_SelLine = 6
lastGoodMenu = menuId
elseif (menuId==0x1010) then
Menu = { MenuId = 0x1010, Text = "Aircraft", PrevId = 0, NextId = 0x1011, BackId = 0x1001, TextId=0 }
MenuLines[5] = { Type = LT_LIST_NC, Text="Aircraft Type", TextId = 0, ValId = MV_AIRCRAFT_TYPE, Min=15, Max=15, Def=15, Val=M_DB[MV_AIRCRAFT_TYPE] }
ctx_SelLine = 5
lastGoodMenu = menuId
elseif (menuId==0x1011) then
Menu = { MenuId = 0x1011, Text = "Model Type: "..aircraft_type_text[currATyp], PrevId = 0, NextId = 0x1020, BackId = 0x1010, TextId=0 }
MenuLines[5] = { Type = LT_LIST_NC, Text="Wing Type", TextId = 0, ValId = MV_WING_TYPE, Min=20, Max=27, Def=20, Val=M_DB[MV_WING_TYPE] }
MenuLines[6] = { Type = LT_LIST_NC, Text="Tail Type", TextId = 0, ValId = MV_TAIL_TYPE, Min=30, Max=40, Def=30, Val=M_DB[MV_TAIL_TYPE] }
ctx_SelLine = 5
lastGoodMenu = menuId
elseif (menuId==0x1020) then
------ WING SETUP -------
local thr = M_DB[MV_CH_THR]
local leftAil = M_DB[MV_CH_L_AIL]
local rightAil = M_DB[MV_CH_R_AIL]
local leftFlap = M_DB[MV_CH_L_FLP]
local rightFlap = M_DB[MV_CH_R_FLP]
local thrText = "Thr"
local leftAilText = "Left Ail"
local rightAilText = "Right Ail"
local leftFlapText = "Left Flap"
local rightFlapText = "Right Flap"
if (rightAil==nil) then leftAilText = "Aileron" end
if (rightFlap==nil) then leftFlapText = "Flap" end
local title = aircraft_type_text[currATyp].." Wing:"..wing_type_text[currWTyp]
Menu = { MenuId = 0x1020, Text = title, PrevId = 0, NextId = 0x1021, BackId = 0x1011, TextId=0 }
MenuLines[0] = { Type = LT_LIST_NC, Text=thrText, TextId = 0, ValId = MV_CH_THR, Min=0, Max=10, Def=0, Val= thr }
MenuLines[2] = { Type = LT_LIST_NC, Text=leftAilText, TextId = 0, ValId = MV_CH_L_AIL, Min=0, Max=9, Def=0, Val= leftAil }
if (rightAil) then
MenuLines[3] = { Type = LT_LIST_NC, Text=rightAilText, TextId = 0, ValId = MV_CH_R_AIL, Min=0, Max=9, Def=0, Val= rightAil }
end
if (leftFlap) then
MenuLines[4] = { Type = LT_LIST_NC, Text=leftFlapText, TextId = 0, ValId = MV_CH_L_FLP, Min=0, Max=9, Def=0, Val= leftFlap }
end
if (rightFlap) then
MenuLines[5] = { Type = LT_LIST_NC, Text=rightFlapText, TextId = 0, ValId = MV_CH_R_FLP, Min=0, Max=9, Def=0, Val= rightFlap }
end
ctx_SelLine = 0
lastGoodMenu = menuId
elseif (menuId==0x1021) then
------ TAIL SETUP -------
local leftRud = M_DB[MV_CH_L_RUD]
local rightRud = M_DB[MV_CH_R_RUD]
local leftEle = M_DB[MV_CH_L_ELE]
local rightEle = M_DB[MV_CH_R_ELE]
local leftRudText = "Left Rud"
local rightRudText = "Right Rud"
local leftElvText = "Left Ele"
local rightElvText = "Right Ele"
if (rightRud==nil) then leftRudText = "Rud" end
if (rightEle==nil) then leftElvText = "Ele" end
local title = aircraft_type_text[currATyp].." Tail:"..tail_type_text[currTTyp]
Menu = { MenuId = 0x1021, Text = title, PrevId = 0, NextId = 0x1001, BackId = 0x1020, TextId=0 }
if (leftRud) then
MenuLines[1] = { Type = LT_LIST_NC, Text=leftRudText, TextId = 0, ValId = MV_CH_L_RUD, Min=0, Max=9, Def=0, Val= leftRud}
end
if (rightRud) then
MenuLines[2] = { Type = LT_LIST_NC, Text=rightRudText, TextId = 0, ValId = MV_CH_R_RUD, Min=0, Max=9, Def=0, Val=rightRud }
end
if (leftEle) then
MenuLines[4] = { Type = LT_LIST_NC, Text=leftElvText, TextId = 0, ValId = MV_CH_L_ELE, Min=0, Max=9, Def=0, Val=leftEle }
end
if (rightEle) then
MenuLines[5] = { Type = LT_LIST_NC, Text=rightElvText, TextId = 0, ValId = MV_CH_R_ELE, Min=0, Max=9, Def=0, Val=rightEle }
end
ctx_SelLine = 1
lastGoodMenu = menuId
elseif (menuId==0x1030) then
Menu = { MenuId = 0x1030, Text = "Gyro Reverse (Port 1-5)", PrevId = 0, NextId = 0x1031, BackId = 0x1001, TextId=0 }
generateGyroReverse(menuId,P1,MV_P1_MODE)
lastGoodMenu = menuId
elseif (menuId==0x1031) then
Menu = { MenuId = 0x1031, Text = "Gyro Reverse (Port 6-10)", PrevId = 0x1030, NextId = 0, BackId = 0x1001, TextId=0 }
generateGyroReverse(menuId,P6,MV_P6_MODE)
lastGoodMenu = menuId
elseif (menuId==0xFFF9) then
ChangePhase(PH_EXIT_DONE)
return
else
Menu = { MenuId = 0x0002, Text = "NOT IMPLEMENTED", TextId = 0, PrevId = 0, NextId = 0, BackId = lastGoodMenu }
ctx_SelLine = -1 -- BACK BUTTON
end
for i = 0, 6 do
if (MenuLines[i].Type > 0) then
MenuLinePostProcessing(MenuLines[i])
end
end
gc()
end
-- Inital List and Image Text for this menus
local function ST_Init_Text(rxId)
-- Channel Names use the Port Text Retrived from OTX/ETX
local p = 0
for i = 0, 9 do List_Text[i] = MODEL.PORT_TEXT[i] end
List_Text[10] = "--"
-- Aircraft Type
List_Text[15+AT_PLANE] = "Airplane";
-- Wing Types
p = 20+WT_A1; List_Text[p] = "Single Ail"; --List_Text_Img[p] = "x.png|Single Aileron"
p = 20+WT_A2; List_Text[p] = "Dual Ail"; --List_Text_Img[p] = "x.png|Dual Aileron"
p = 20+WT_FLPR; List_Text[p] = "Flaperon"; --List_Text_Img[p] = "x.png|Flaperon"
p = 20+WT_A1_F1; List_Text[p] = "Ail + Flap"; --List_Text_Img[p] = "x.png|Aileron + Flap"
p = 20+WT_A2_F1; List_Text[p] = "Dual Ail + Flap"; --List_Text_Img[p] = "x.png|Dual Aileron + Flap"
p = 20+WT_A2_F2; List_Text[p] = "Dual Ail + Dual Flap"; --List_Text_Img[p] = "x.png|Dual Aileron + Dual Flap"
p = 20+WT_ELEVON_A; List_Text[p] = "Delta A"; --List_Text_Img[p] = "x.png|Delta/Elevon A"
p = 20+WT_ELEVON_B; List_Text[p] = "Delta B"; --List_Text_Img[p] = "x.png|Delta/Elevon B"
-- Tail Types
p = 30+TT_R1; List_Text[p] = "Rudder Only"; --List_Text_Img[p] = "x.png|Rudder Only"
p = 30+TT_R1_E1; List_Text[p] = "Rud + Ele"; --List_Text_Img[p] = "x.png|Tail Normal"
p = 30+TT_R1_E2; List_Text[p] = "Rud + Dual Ele"; --List_Text_Img[p] = "x.png|Rud + Dual Ele"
p = 30+TT_R2_E1; List_Text[p] = "Dual Rud + Ele"; --List_Text_Img[p] = "x.png|Dual Rud + Ele"
p = 30+TT_R2_E2; List_Text[p] = "Dual Rud + Dual Ele"; --List_Text_Img[p] = "x.png|Dual Rud + Dual Elev"
p = 30+TT_VT_A; List_Text[p] = "V-Tail A"; --List_Text_Img[p] = "x.png|V-Tail A"
p = 30+TT_VT_B; List_Text[p] = "V-Tail B"; --List_Text_Img[p] = "x.png|V-Tail B"
p = 30+TT_TLRN_A; List_Text[p] = "Taileron A"; --List_Text_Img[p] = "x.png|Taileron A"
p = 30+TT_TLRN_B; List_Text[p] = "Taileron B"; --List_Text_Img[p] = "x.png|Taileron B"
p = 30+TT_TLRN_A_R2; List_Text[p] = "Taileron A + 2x Rud"; --List_Text_Img[p] = "x.png|Taileron A + Dual Rud"
p = 30+TT_TLRN_B_R2; List_Text[p] = "Taileron B + 2x Rud"; --List_Text_Img[p] = "x.png|Taileron B + Dual Rud"
-- Servo Reverse
List_Text[45+MT_NORMAL] = "Normal"
List_Text[45+MT_REVERSE] = "Reverse"
end
-- Initial Setup
local function ST_Init()
ST_Init_Text(0)
gc()
-- Setup default Data if no data loaded
menuDataChanged = false
if (M_DB[MV_AIRCRAFT_TYPE]==nil) then
ST_Default_Data()
menuDataChanged = true
end
currATyp = M_DB[MV_AIRCRAFT_TYPE]
currWTyp = M_DB[MV_WING_TYPE]
currTTyp = M_DB[MV_TAIL_TYPE]
Phase = PH_RX_VER
end
----- Line Type
local function isSelectable(line)
if (line.Type == LT_MENU and line.ValId == line.MenuId) then return false end -- Menu to same page
if (line.Type ~= LT_MENU and line.Max == 0) then return false end -- Read only data line
if (line.Type ~= 0 and line.TextId < 0x8000) then return true end -- Not Flight Mode
return false;
end
local function isListLine(line)
return line.Type==LT_LIST_NC
end
local function isEditing()
return ctx_EditLine ~= nil
end
-----------------------
local function Get_Text(index)
local out = Text[index] or string.format("Unknown_%X", index)
return out
end
local function Get_Text_Value(index)
local out = List_Text[index] or Get_Text(index)
return out
end
function ChangePhase(newPhase)
Phase = newPhase
end
local function Value_Add(dir)
local line = MenuLines[ctx_SelLine]
local inc = dir
line.Val = line.Val + inc
if line.Val > line.Max then
line.Val = line.Max
elseif line.Val < line.Min then
line.Val = line.Min
end
end
--------------
local function GotoMenu(menuId, lastSelectedLine)
Menu.MenuId = menuId
ctx_SelLine = lastSelectedLine
ChangePhase(PH_TITLE)
end
local function DSM_HandleEvent(event)
if event == EVT_VIRTUAL_EXIT then
if Phase == PH_RX_VER then
Phase = PH_EXIT_DONE -- Exit program
else
if isEditing() then -- Editing a Line, need to restore original value
MenuLines[ctx_EditLine].Val = originalValue
event = EVT_VIRTUAL_ENTER
else
if (Menu.BackId > 0 ) then -- Back??
ctx_SelLine = -1 --Back Button
event = EVT_VIRTUAL_ENTER
else
ChangePhase(PH_EXIT_REQ)
end
end
end
end -- Exit
if Phase == PH_RX_VER then return end -- nothing else to do
if event == EVT_VIRTUAL_NEXT then
if isEditing() then -- Editting?
Value_Add(1)
else
if ctx_SelLine < 7 then -- On a regular line
local num = ctx_SelLine -- Find the prev selectable
for i = ctx_SelLine + 1, 6, 1 do
local line = MenuLines[i]
if isSelectable(line) then
ctx_SelLine = i
break
end
end
if num == ctx_SelLine then -- No Selectable Line
if Menu.NextId ~= 0 then
ctx_SelLine = 7 -- Next
elseif Menu.PrevId ~= 0 then
ctx_SelLine = 8 -- Prev
end
end
elseif Menu.PrevId ~= 0 then
ctx_SelLine = 8 -- Prev
end
end
return
end
if event == EVT_VIRTUAL_PREV then
if isEditing() then -- In Edit Mode
Value_Add(-1)
else
if ctx_SelLine == 8 and Menu.NextId ~= 0 then
ctx_SelLine = 7 -- Next
elseif ctx_SelLine > 0 then
if ctx_SelLine > 6 then
ctx_SelLine = 7 --NEXT
end
local num = ctx_SelLine -- Find Prev Selectable line
for i = ctx_SelLine - 1, 0, -1 do
local line = MenuLines[i]
if isSelectable(line) then
ctx_SelLine = i
break
end
end
if num == ctx_SelLine then -- No Selectable Line
if (Menu.BackId > 0) then
ctx_SelLine = -1 -- Back
end
end
else
ctx_SelLine = -1 -- Back
end
end
return
end
if event == EVT_VIRTUAL_ENTER then
if ctx_SelLine == -1 then -- Back
GotoMenu(Menu.BackId, 0x80)
elseif ctx_SelLine == 7 then -- Next
GotoMenu(Menu.NextId, 0x82)
elseif ctx_SelLine == 8 then -- Prev
GotoMenu(Menu.PrevId, 0x81)
elseif ctx_SelLine >= 0 and MenuLines[ctx_SelLine].Type == LT_MENU then
GotoMenu(MenuLines[ctx_SelLine].ValId, ctx_SelLine) -- ValId is the next menu
else
-- value entry
if isEditing() then
ctx_EditLine = nil -- Done Editting
ChangePhase(PH_VAL_EDIT_END)
else -- Start Editing
ctx_EditLine = ctx_SelLine
originalValue = MenuLines[ctx_SelLine].Val
ChangePhase(PH_VAL_EDITING)
end
end
end
end
local function DSM_Send_Receive()
if Phase == PH_RX_VER then -- request RX version
Phase = PH_TITLE
Menu.MenuId = 0x01001
Refresh_Display = true
elseif Phase == PH_WAIT_CMD then
elseif Phase == PH_TITLE then -- request menu title
ST_LoadMenu(Menu.MenuId)
if (Phase~=PH_EXIT_DONE) then
Phase = PH_WAIT_CMD
end
Refresh_Display = true
elseif Phase == PH_VAL_EDIT_END then -- send value
local line = MenuLines[ctx_SelLine] -- Updated Value of SELECTED line
-- Update the menu data from the line
if (M_DB[line.ValId] ~= line.Val ) then
M_DB[line.ValId] = line.Val
print(string.format("MENU_DATA[%d/%s]=%d",line.ValId,line.Text, line.Val))
menuDataChanged=true
end
-- Did the Wing type change?
local wt = M_DB[MV_WING_TYPE]
if (currWTyp ~= wt) then
currWTyp = wt
ST_PlaneWingInit(currWTyp)
-- DELTA has only RUDER
if (currWTyp==WT_ELEVON_A or currWTyp==WT_ELEVON_B) then
M_DB[MV_TAIL_TYPE] = TT_R1
end
end
--- Did the tail changed?
local tt = M_DB[MV_TAIL_TYPE]
if (currTTyp ~= tt) then
if (not tailTypeCompatible(currTTyp,tt)) then
ST_PlaneTailInit(tt)
end
currTTyp = tt
end
Phase = PH_WAIT_CMD
elseif Phase == PH_EXIT_REQ then
Phase=PH_EXIT_DONE
end
end
-----
local function showBitmap(x, y, imgDesc)
local f = string.gmatch(imgDesc, '([^%|]+)') -- Iterator over values split by '|'
local imgName, imgMsg = f(), f()
f = string.gmatch(imgMsg or "", '([^%:]+)') -- Iterator over values split by ':'
local p1, p2 = f(), f()
lcd.drawText(x, y, p1 or "", TEXT_ATTR) -- Alternate Image MSG
lcd.drawText(x, y + LCD_Y_LINE_HEIGHT, p2 or "", TEXT_ATTR) -- Alternate Image MSG
gc()
end
local function drawButton(x, y, text, active)
local attr = TEXT_ATTR
if (active) then attr = attr + INVERS end
lcd.drawText(x, y, text, attr)
end
local function DSM_Display()
lcd.clear()
--Draw RX Menu
if Phase == PH_RX_VER then
return
end
-- display Program version or RX version
local msg = "FProg "..VERSION
lcd.drawText(40, LCD_Y_LOWER_BUTTONS, msg, TEXT_ATTR)
if Menu.MenuId == 0 then return end; -- No Title yet
-- Got a Menu
lcd.drawText(1, 0, Menu.Text, TEXT_ATTR + INVERS)
local y = LCD_Y_LINE_HEIGHT + 2
for i = 0, 6 do
local attrib = TEXT_ATTR
if (i == ctx_SelLine) then attrib = attrib + INVERS end -- Selected Line
local line = MenuLines[i]
if line ~= nil and line.Type ~= 0 then
local heading = line.Text
local text = nil
if line.Type ~= LT_MENU then -- list/value
if line.Val ~= nil then
if isListLine(line) then
local textId = line.Val + line.TextStart
text = Get_Text_Value(textId)
--local imgDesc = List_Text_Img[textId]
--if (imgDesc and i == ctx_SelLine) then -- Optional Image and Msg for selected value
-- showBitmap(1, 20, imgDesc)
--end
else
text = line.Val
end
end -- if is Value
if (ctx_EditLine == i) then -- Editing a Line
attrib = BLINK + INVERS + TEXT_ATTR
end
lcd.drawText(LCD_X_MAX, y, text or "--", attrib + RIGHT) -- display value
--lcd.drawText(LCD_X_MAX, y, line.Format or "", TEXT_ATTR + RIGHT) -- display Format
attrib = TEXT_ATTR
end
lcd.drawText(1, y, heading, attrib) -- display text
end
y = y + LCD_Y_LINE_HEIGHT
end -- for
if Menu.BackId~=0 then
drawButton(LCD_X_RIGHT_BUTTONS, 0, "Back", ctx_SelLine == -1)
end
if Menu.NextId~=0 then
drawButton(LCD_X_RIGHT_BUTTONS, LCD_Y_LOWER_BUTTONS, "Next", ctx_SelLine == 7)
end
if Menu.PrevId~=0 then
drawButton(1, LCD_Y_LOWER_BUTTONS, "Prev", ctx_SelLine == 8)
end
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
--LOG_open()
ST_Init()
gc()
if (LCD_W > 128) then
TEXT_ATTR = 0
LCD_Y_LINE_HEIGHT = 25
LCD_X_MAX = 300
LCD_X_RIGHT_BUTTONS = LCD_X_MAX - 30
LCD_Y_LOWER_BUTTONS = (8 * LCD_Y_LINE_HEIGHT) + 2
end
Phase = PH_RX_VER
end
-- Main
local function DSM_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
end
DSM_Display()
DSM_HandleEvent(event)
DSM_Send_Receive()
gc()
if Phase == PH_EXIT_DONE then
LOG_close()
return 2
else
return 0
end
end
---
-- Load Model Config
gc()
local r = assert(loadScript(DSMLIB_PATH.."DsmMIN_P1.lua"), "Not-Found: DSMLIB/DsmMIN_P1.lua")
(MODEL,M_DB, LOG_write)
gc()
----
return { init = DSM_Init, run = DSM_Run }