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 }