diff --git a/Lua_scripts/DSM FwdPrg_05_BW.lua b/Lua_scripts/DSM FwdPrg_05_BW.lua index 3ef3a12..aa71f4a 100644 --- a/Lua_scripts/DSM FwdPrg_05_BW.lua +++ b/Lua_scripts/DSM FwdPrg_05_BW.lua @@ -1,5 +1,5 @@ -local toolName = "TNS|DSM Forward Prog v0.5 (Text B&W) |TNE" -local VERSION = "v0.5" +local toolName = "TNS|DSM Forward Prog v0.51 (Text B&W) |TNE" +local VERSION = "v0.51" ---- ######################################################################### ---- # # @@ -33,13 +33,7 @@ local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/" -local dsmLib -if (SIMULATION_ON) then - -- library with SIMILATION VERSION. Works really well in Companion for GUI development - dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgSIMLib.lua"), "Not-Found: DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON) -else - dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON) -end +local dsmLib = assert(loadScript(DSMLIB_PATH.."DsmSetupLib.lua"), "Not-Found: DSMLIB/DsmSetupLib.lua")(DEBUG_ON,SIMULATION_ON) local PHASE = dsmLib.PHASE local LINE_TYPE = dsmLib.LINE_TYPE @@ -78,12 +72,29 @@ local originalValue = nil local warningScreenON = true ------------------------------------------------------------------------------------------------------------ -local function GUI_SwitchSimulationOFF() +local function GUI_SwitchToRX() + -- Force to refresh DSM Info in MODEL (dsmLib pointing to the setup Script) + local dsmChannelInfo, description = dsmLib.CreateDSMPortChannelInfo() + dsmLib.ReleaseConnection() dsmLib.LOG_close() SIMULATION_ON = false - dsmLib = loadScript(DSMLIB_PATH .. "DsmFwPrgLib.lua")(DEBUG_ON) + dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON) + DSM_Context = dsmLib.DSM_Context + + dsmLib.Init(toolName) -- Initialize Library + dsmLib.SetDSMChannelInfo(dsmChannelInfo, description) -- send the dsmChannelInfo to new instance library + dsmLib.StartConnection() + DSM_Context.Refresh_Display = true +end + +local function GUI_SwitchToSIM() + dsmLib.ReleaseConnection() + dsmLib.LOG_close() + + SIMULATION_ON = true + dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgSIMLib.lua"), "Not-Found: DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON) DSM_Context = dsmLib.DSM_Context dsmLib.Init(toolName) -- Initialize Library @@ -274,7 +285,7 @@ local function GUI_Display() value = dsmLib.Get_List_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text local imgData = dsmLib.Get_List_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display?? - if (imgData) then -- Optional Image and Msg for value + if (imgData and i == ctx.SelLine) then -- Optional Image and Msg for selected value GUI_ShowBitmap(LCD_X_LINE_TITLE,LCD_Y_LINE_FIRST+LCD_Y_LINE_HEIGHT, imgData) end end @@ -372,12 +383,14 @@ local function GUI_HandleEvent(event, touchState) dsmLib.GotoMenu(menu.PrevId,0) elseif menuLines[ctx.SelLine].ValId ~= 0 then if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Next menu exist - if (SIMULATION_ON and menuLines[ctx.SelLine].ValId==0xFFFF) then - -- SPECIAL Simulation menu to Exit Simulation and - -- comunicate with Real RX - GUI_SwitchSimulationOFF() + if (menuLines[ctx.SelLine].ValId==0xFFF1) then + -- SPECIAL Simulation menu to Simulator + GUI_SwitchToSIM() + elseif (menuLines[ctx.SelLine].ValId==0xFFF2) then + -- SPECIAL Simulation menu to go to RX + GUI_SwitchToRX() else - dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId,ctx.SelLine) -- ValId is the MenuId to navigate to + dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId, ctx.SelLine) -- ValId is the MenuId to navigate to end else -- Editing a Line???? @@ -432,16 +445,15 @@ local function GUI_Warning(event) lcd.drawFilledRectangle(0, 0, LCD_W, 17, TITLE_BGCOLOR) lcd.drawText(5, 0, header, MENU_TITLE_COLOR + TEXT_SIZE) + lcd.drawText(100,20,"INFO", BOLD) + lcd.drawText(5,40,"DSM Forward programing shares TX Servo/Output settings", 0) + lcd.drawText(5,60,"with the RX. Make sure you setup your plane first in ", 0) + lcd.drawText(5,80,"the TX before your start programming your RX.", 0) + lcd.drawText(5,100,"Wing & Tail type can be configured using this tool.", 0) - lcd.drawText(100,20,"WARNING", BLINK+BOLD) - lcd.drawText(5,40,"Gyro settings-> Initial Setup and Initial SAFE Setup", BOLD) - lcd.drawText(5,70,"Has only been tested with normal wing type and normal tail.", 0) - lcd.drawText(5,90,"Make sure that your Gyro/Safe reacts correctly after setup", 0) - lcd.drawText(5,110,"with this tool. If not, set it up with a Spektrum TX.", 0) - - lcd.drawText(5,150,"Gyro settings-> System Setup -> Relearn Servo Setting", BOLD) - lcd.drawText(5,180,"Will override Wing type, tail type, servo reverse, etc.", 0) - lcd.drawText(5,200,"If this RX was initally setup with a Spektrum Transmiter.", 0) + lcd.drawText(5,150,"TX Servo settings are sent to the RX during 'Initial Setup'", 0) + lcd.drawText(5,170,"as well as when using RX menu 'Relearn Servo Settings'", 0) + lcd.drawText(5,200,"ALWAYS TEST Gyro reactions after this conditions before flying.", BOLD) lcd.drawText(100,250," OK ", INVERS + BOLD) diff --git a/Lua_scripts/DSM FwdPrg_05_Color.lua b/Lua_scripts/DSM FwdPrg_05_Color.lua index 1b8740b..b708f81 100644 --- a/Lua_scripts/DSM FwdPrg_05_Color.lua +++ b/Lua_scripts/DSM FwdPrg_05_Color.lua @@ -1,5 +1,5 @@ -local toolName = "TNS|DSM Forward Prog v0.5 (Color+Touch) |TNE" -local VERSION = "v0.5" +local toolName = "TNS|DSM Forward Prog v0.51 (Color+Touch) |TNE" +local VERSION = "v0.51" ---- ######################################################################### ---- # # @@ -27,20 +27,14 @@ local VERSION = "v0.5" -- Rewrite/Enhancements By: Francisco Arzu ------------------------------------------------------------------------------ -local SIMULATION_ON = false -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX +local SIMULATION_ON = true -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log) local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX local USE_SPECKTRUM_COLORS = true -- true: Use spectrum colors, false: use theme colors (default on OpenTX) local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/" local IMAGE_PATH = DSMLIB_PATH .. "img/" -local dsmLib -if (SIMULATION_ON) then - -- library with SIMILATION VERSION. Works really well in Companion for GUI development - dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgSIMLib.lua"), "Not-Found: DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON) -else - dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON) -end +local dsmLib = assert(loadScript(DSMLIB_PATH.."DsmSetupLib.lua"), "Not-Found: DSMLIB/DsmSetupLib.lua")(DEBUG_ON,SIMULATION_ON) local PHASE = dsmLib.PHASE local LINE_TYPE = dsmLib.LINE_TYPE @@ -104,12 +98,29 @@ local function my_lcd_sizeText(s) end -local function GUI_SwitchSimulationOFF() +local function GUI_SwitchToRX() + -- Force to refresh DSM Info in MODEL (dsmLib pointing to the setup Script) + local dsmChannelInfo, description = dsmLib.CreateDSMPortChannelInfo() + dsmLib.ReleaseConnection() dsmLib.LOG_close() SIMULATION_ON = false - dsmLib = loadScript(DSMLIB_PATH .. "DsmFwPrgLib.lua")(DEBUG_ON) + dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON) + DSM_Context = dsmLib.DSM_Context + + dsmLib.Init(toolName) -- Initialize Library + dsmLib.SetDSMChannelInfo(dsmChannelInfo, description) -- send the dsmChannelInfo to new instance library + dsmLib.StartConnection() + DSM_Context.Refresh_Display = true +end + +local function GUI_SwitchToSIM() + dsmLib.ReleaseConnection() + dsmLib.LOG_close() + + SIMULATION_ON = true + dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgSIMLib.lua"), "Not-Found: DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON) DSM_Context = dsmLib.DSM_Context dsmLib.Init(toolName) -- Initialize Library @@ -404,7 +415,7 @@ local function GUI_Display() value = dsmLib.Get_List_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text local imgData = dsmLib.Get_List_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display?? - if (imgData) then -- Optional Image and Msg for value + if (imgData and i == ctx.SelLine) then -- Optional Image and Msg for selected value GUI_ShowBitmap(LCD_X_LINE_TITLE,LCD_Y_LINE_START, imgData) end end @@ -564,9 +575,12 @@ local function GUI_HandleEvent(event, touchState) elseif menuLines[ctx.SelLine].ValId ~= 0 then -- Menu or Value if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Navigate to Menu - if (SIMULATION_ON and menuLines[ctx.SelLine].ValId==0xFFFF) then - -- SPECIAL Simulation menu to Exit Simulation - GUI_SwitchSimulationOFF() + if (menuLines[ctx.SelLine].ValId==0xFFF1) then + -- SPECIAL Simulation menu to Simulator + GUI_SwitchToSIM() + elseif (menuLines[ctx.SelLine].ValId==0xFFF2) then + -- SPECIAL Simulation menu to go to RX + GUI_SwitchToRX() else dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId, ctx.SelLine) -- ValId is the MenuId to navigate to end @@ -618,16 +632,15 @@ local function GUI_Warning(event,touchState) lcd.drawFilledRectangle(0, 0, LCD_W, 17, LCD_TOOL_HDR_BGCOLOR) lcd.drawText(5, 0, header, LCD_TOOL_HDR_COLOR + SMLSIZE) + lcd.drawText(100,20,"INFO", BOLD) + lcd.drawText(5,40,"DSM Forward programing shares TX Servo/Output settings", 0) + lcd.drawText(5,60,"with the RX. Make sure you setup your plane first in ", 0) + lcd.drawText(5,80,"the TX before your start programming your RX.", 0) + lcd.drawText(5,100,"Wing & Tail type can be configured using this tool.", 0) - lcd.drawText(100,20,"WARNING", BLINK+BOLD) - lcd.drawText(5,40,"Gyro settings-> Initial Setup and Initial SAFE Setup", BOLD) - lcd.drawText(5,70,"Has only been tested with normal wing type and normal tail.", 0) - lcd.drawText(5,90,"Make sure that your Gyro/Safe reacts correctly after setup", 0) - lcd.drawText(5,110,"with this tool. If not, set it up with a Spektrum TX.", 0) - - lcd.drawText(5,150,"Gyro settings-> System Setup -> Relearn Servo Setting", BOLD) - lcd.drawText(5,180,"Will override Wing type, tail type, servo reverse, etc.", 0) - lcd.drawText(5,200,"If this RX was initally setup with a Spektrum Transmiter.", 0) + lcd.drawText(5,150,"TX Servo settings are sent to the RX during 'Initial Setup'", 0) + lcd.drawText(5,170,"as well as when using RX menu 'Relearn Servo Settings'", 0) + lcd.drawText(5,200,"ALWAYS TEST Gyro reactions after this conditions before flying.", BOLD) lcd.drawText(100,250," OK ", INVERS + BOLD) diff --git a/Lua_scripts/DSMLIB/DsmFwPrgLib.lua b/Lua_scripts/DSMLIB/DsmFwPrgLib.lua index a3442c1..cecb7fe 100644 --- a/Lua_scripts/DSMLIB/DsmFwPrgLib.lua +++ b/Lua_scripts/DSMLIB/DsmFwPrgLib.lua @@ -40,8 +40,8 @@ local DEBUG_ON = ... -- Get Debug_ON from parameters. -- 0=NO DEBUG, 1=HIGH LEVEL 2=MORE DETAILS -local LIB_VERSION = "0.5" - +local LIB_VERSION = "0.51" +local TRANSLATE_AETR_TO_TAER = true -- TRANSLATE TX channel info from AETR to TAER local Lib = { Init_Text = function (rxId) end } --RX IDs-- @@ -82,6 +82,23 @@ local LINE_TYPE = { LT_EMPTY = 0x00 } +--Channel Types -- +local CH_TYPE = { + NONE = 0x00, + AIL = 0x01, + ELE = 0x02, + RUD = 0x04, + + REVERSE = 0x20, + THR = 0x40, + SLAVE = 0x80, +} + +local CH_MIX_TYPE = { + NONE = 0x00, + MIX_ELE = 0x20, -- For VTIAL and Delta-ELEVON +} + local DISP_ATTR = { BOLD = 0x01, RIGHT=0x02, CENTER=0x04, PERCENT = 0x10, DEGREES=0x20, FORCED_MENU = 0x40 } @@ -99,6 +116,15 @@ local DSM_Context = { isReset = false -- false when starting from scracts, true when starting from Reset } +-- MODEL information from ETX/OTX +local MODEL = { + modelName = "", -- The name of the model comming from OTX/ETX + modelOutputChannel = {}, -- Output information from OTX/ETX + PORT_TEXT = {}, + DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script +} + + local MAX_MENU_LINES = 6 local BACK_BUTTON = -1 -- Tread it as a display line #-1 local NEXT_BUTTON = MAX_MENU_LINES + 1 -- Tread it as a display line #7 @@ -119,6 +145,7 @@ local PhaseText = {} local LineTypeText = {} local RxName = {} + local Text = {} -- Text for Menu and Menu Lines (Headers only) local List_Text = {} -- Messages for List Options (values only) local List_Text_Img = {} -- If the Text has Attached Images @@ -127,8 +154,43 @@ local List_Values = {} -- Additiona restrictions on List Values when non co local LOG_FILE = "/LOGS/dsm_log.txt" local logFile = nil + function DSM_Context.isEditing() return DSM_Context.EditLine~=nil end + +---- DSM_ChannelInfo --------------------------------- +-- First byte describe Special Mixing (Vtail/Elevon = 0x20) +--VTAIL +--(0x00 0x06) CH_TYPE.ELE+CH_TYPE.RUD (0x02+0x04 = 0x06) +--(0x20 0x86) CH_TYPE.ELE+CH_TYPE.RUD+CH_TYPE.SLAVE (0x02+0x04+0x80 = 0x86) + +-- The 2nd byte describes the functionality of the port +-- +-- Single Example: CH_TYPE.AIL (0x01) Aileron +-- Reverse Example: CH_TYPE.AIL+CH_TYPE.REVERSE (0x01+0x20=0x21) Reverse Aileron +-- Slave Example: CH_TYPE.AIL+CH_TYPE.SLAVE (0x01+0x80) -- 2nd servo Aileron + +-- Elevon Example: CH_TYPE.AIL+CH_TYPE.ELE (0x01+0x02 = 0x03) -- Elevon +-- Elevon Example: CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE (0x01+0x02+0x80 = 0x83) -- Slave Elevon + +-- RudElv (VTail) Example: CH_TYPE.ELE+CH_TYPE.RUD (0x02+0x04 = 0x06) -- Rudevator +-- RudElv (VTail) Example: CH_TYPE.ELE+CH_TYPE.RUD+CH_TYPE.SLAVE (0x02+0x04+0x80 = 0x86) -- Rudevator Slave + +-- DEFAULT Simple Plane Port configuration (The Configuration tool will overrride this) +MODEL.DSM_ChannelInfo= {[0]= -- Start array at position 0 + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.THR}, -- Ch1 Thr (0x40) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.AIL}, -- Ch2 Ail (0x01) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.ELE}, -- Ch2 ElE (0x02) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.RUD}, -- Ch4 Rud (0x04) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.NONE}, -- Ch5 Gear (0x00) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.NONE}, -- Ch6 Aux1 (0x00) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.NONE}, -- Ch7 Aux2 (0x00) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.NONE}, -- Ch8 Aux3 (0x00) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.NONE}, -- Ch9 Aux4 (0x00) + {[0]= CH_MIX_TYPE.NONE, CH_TYPE.NONE} -- Ch10 Aux5 (0x00) + } + + ------------------------------------------------------------------------------------------------------------ local logCount=0 local function LOG_open() @@ -140,6 +202,7 @@ local function LOG_write(...) local str = string.format(...) io.write(logFile, str) + str = string.gsub(str,"\n"," ") -- Elimitate return from line, since print will do it print(str) if (logCount > 10) then -- Close an re-open the file @@ -315,6 +378,21 @@ local function menuLine2String(l) return txt end +local function channelType2String(byte1, byte2) + local s = "" + + if (bit32.band(byte2,CH_TYPE.AIL)>0) then s=s.."AIL " end + if (bit32.band(byte2,CH_TYPE.ELE)>0) then s=s.."ELE " end + if (bit32.band(byte2,CH_TYPE.RUD)>0) then s=s.."RUD " end + if (bit32.band(byte2,CH_TYPE.THR)>0) then s=s.."THR " end + if (bit32.band(byte2,CH_TYPE.SLAVE)>0) then s=s.."SLAVE " end + if (bit32.band(byte2,CH_TYPE.REVERSE)>0) then s=s.."REVERSE " end + + if (bit32.band(byte1,CH_MIX_TYPE.MIX_ELE)>0) then s=s.."*MIX_ELE_0x20? " end + + return s; +end + ------------------------------------------------------------------------------------------------------------ local function multiBuffer2String() -- used for debug @@ -450,8 +528,75 @@ local function DSM_send(...) end end ------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------- +-- Read the model information from OTX/ETX +local function DSM_ReadTxModelData() + local table = model.getInfo() -- Get the model name + MODEL.modelName = table.name + local module = model.getModule(0) -- Internal + if (module==nil) then module = model.getModule(1) end -- External + if (module~=nil) then + if (module.Type==6 ) then -- MULTI-MODULE + local chOrder = module.channelsOrder + LOG_write("MultiChannel Ch Order: [%s]\n",chOrder) + end + end + + LOG_write("MODEL NAME = %s\n",MODEL.modelName) + + -- Read Ch1 to Ch10 + local i= 0 + for i = 0, 9 do + local ch = model.getOutput(i) -- Zero base + if (ch~=nil) then + MODEL.modelOutputChannel[i] = ch + if (string.len(ch.name)==0) then + ch.formatName = string.format("TX:Ch%i",i+1) + else + ch.formatName = string.format("TX:Ch%i/%s",i+1,ch.name or "--") + end + end + end + + -- Translate AETR to TAER + -- TODO: Check if there is a way to know how to the TX is configured, since if it is + -- already TAER, is not needed + + if (TRANSLATE_AETR_TO_TAER) then + LOG_write("Applying AETR -> TAER translation\n") + local ail = MODEL.modelOutputChannel[0] + local elv = MODEL.modelOutputChannel[1] + local thr = MODEL.modelOutputChannel[2] + + MODEL.modelOutputChannel[0] = thr + MODEL.modelOutputChannel[1] = ail + MODEL.modelOutputChannel[2] = elv + end + + -- Create the Port Text to be used + LOG_write("Ports/Channels:\n") + for i = 0, 9 do + local ch = MODEL.modelOutputChannel[i] + if (ch~=nil) then + MODEL.PORT_TEXT[i] = string.format("Port%i (%s) ",i+1,ch.formatName) + LOG_write("Port%d %s [%d,%d] Rev=%d, Off=%d, ppmC=%d, syn=%d\n",i+1,ch.formatName,math.floor(ch.min/10),math.floor(ch.max/10), ch.revert, ch.offset, ch.ppmCenter, ch.symetrical) + end + end +end + +local function DSM_SetDSMChannelInfo(channelInfo, description) + MODEL.DSM_ChannelInfo = channelInfo + + LOG_write("Current Model Generated Port Configuration\n") + LOG_write("Description:%s\n",description) + for i = 0, 9 do + local b1, b2 = channelInfo[i][0], channelInfo[i][1] + LOG_write("%s (0x%02X, 0x%02X) = %s \n",MODEL.PORT_TEXT[i],b1,b2, channelType2String(b1,b2)) + end +end + +------------------------------------------------------------------------------------------------- local function DSM_StartConnection() if (DEBUG_ON) then LOG_write("DSM_StartConnection()\n") end @@ -666,73 +811,104 @@ local function DSM_menuValueChangingWait(valId, text, line) -- Pascal: i think the 2nd byte is the leghts of the entire message in bytes, so instead of 0x06, should be 0x04 for here.. work both ways end -local function DSM_sentTxInfo(menuId,curLine) - if (TxInfo_Step == 0 and TxInfo_Type==0x00) then - -- AR636B.. but does not work - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_22(#%d DATA=TX: 0x22 0x04 %02X %02X)\n", curLine, - 0x00, 0x00) -- DATA part - end - DSM_send(0x22, 0x04, 0x00, 0x00) +-- Send the functionality of the RX channel Port (channel) +local function DSM_sendTxChInfo_20(portNo) + local b1,b2 = MODEL.DSM_ChannelInfo[portNo][0], MODEL.DSM_ChannelInfo[portNo][1] - elseif (TxInfo_Step == 0 and (TxInfo_Type==0x01 or TxInfo_Type==0x1F)) then + if (DEBUG_ON) then LOG_write("CALL DSM_TxChInfo_20(#%d %s DATA= %02X %02X %02X %02X) CONTEXT: %s\n", portNo, MODEL.PORT_TEXT[portNo], + portNo, portNo, b1, b2, channelType2String(b1,b2)) -- DATA part + end + DSM_send(0x20, 0x06, portNo, portNo, b1, b2) +end + +local function DSM_sendTxSubtrim_21(portNo) + --SubTrim is encoded as an offset of the pulse width. + + local data = {[0]= -- Start at 0 + {[0]= 0x0, 0x00, 0x07, 0xFF }, -- Ch1 Thr: 0 00 07 FF Subtrim ?? + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch2 Ail: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch3 Elev: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch4 Rud: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch5 Gear: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch6 Aux1: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch7 Aux2: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch8 Aux3: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch9 Aux4: 0 8E 07 72 Subtrim 0 + {[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch10 Aux5: 0 8E 07 72 Subtrim 0 + } + + local b1,b2,b3,b4 = data[portNo][0], data[portNo][1], data[portNo][2], data[portNo][3] + + if (DEBUG_ON) then LOG_write("CALL DSM_TxSubtrim_21(#%d %s DATA=%02X %02X %02X %02X)\n", portNo, MODEL.PORT_TEXT[portNo], + b1,b2,b3,b4) -- DATA part + end + DSM_send(0x21, 0x06, b1,b2,b3,b4) -- Port is not send anywhere, since the previous 0x20 type message have it. +end + +local function DSM_sendTxServoTravel_23(portNo) + local leftTravel = math.abs(math.floor(MODEL.modelOutputChannel[portNo].min/10)) + local rightTravel = math.abs(math.floor(MODEL.modelOutputChannel[portNo].max/10)) + local debugInfo = string.format("Travel L/R (%d - %d)",leftTravel,rightTravel) + + if (DEBUG_ON) then LOG_write("CALL DSM_TxServoTravel_23(#%d %s DATA= %02X %02X %02X %02X) CONTEXT: %s\n", portNo, MODEL.PORT_TEXT[portNo], + 0x00, leftTravel, 0x00, rightTravel, debugInfo) -- DATA part + end + DSM_send(0x23, 0x06, 0x00, leftTravel, 0x00, rightTravel) +end + +local function DSM_sentTxInfo(menuId,portNo) + -- TxInfo_Type=0 : AR636B Main Menu (Send port/Channel info + SubTrim + Travel) + -- TxInfo_Type=1 : AR630-637 Famly Main Menu (Only Send Port/Channel usage Msg 0x20) + -- TxInfo_Type=1F : AR630-637 Initial Setup/Relearn Servo Settings (Send port/Channel info + SubTrim + Travel +0x24/Unknown) + + if (TxInfo_Step == 0) then -- AR630 family: Both TxInfo_Type (ManinMenu=0x1, Other First Time Configuration = 0x1F) - - local last_byte = { 0x40, 0x01, 0x02, 0x04, 0x00, 0x00 } -- unknown. - - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_20(#%d DATA=TX: 0x20 0x06 %02X %02X %02X %02X)\n", curLine, - curLine, curLine, 0, last_byte[curLine + 1]) -- DATA part - end - DSM_send(0x20, 0x06, curLine, curLine, 0x00, last_byte[curLine + 1]) -- line X - TxInfo_Step = TxInfo_Step + 1 + DSM_sendTxChInfo_20(portNo) if (TxInfo_Type == 0x1F) then Waiting_RX = 0 -- keep Transmitig + TxInfo_Step = 1 end - elseif (TxInfo_Step == 1 and TxInfo_Type==0x1F) then - -- 23,6: 0 64 0 64 - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_23(#%d DATA=TX: 0x23 0x06 %02X %02X %02X %02X)\n", curLine, - 0x00, 0x64, 0x00, 0x64) -- DATA part - end - DSM_send(0x23, 0x06, 0x00, 0x64, 0x00, 0x64) - TxInfo_Step = TxInfo_Step + 1 + if (TxInfo_Type == 0x00) then + Waiting_RX = 0 -- keep Transmitig + TxInfo_Step = 2 + end + elseif (TxInfo_Step == 1) then + DSM_sendTxServoTravel_23(portNo) + TxInfo_Step = 2 Waiting_RX = 0 -- keep Transmitig - elseif (TxInfo_Step == 2 and TxInfo_Type==0x1F) then - local data = { - { 0x0, 0x00, 0x07, 0xFF }, -- #0: 0 00 07 FF - { 0x0, 0x8E, 0x07, 0x72 }, -- #1: 0 8E 07 72 - { 0x0, 0x8E, 0x07, 0x72 }, -- #2: 0 8E 07 72 - { 0x0, 0x8E, 0x07, 0x72 } -- #3: 0 8E 07 72 - } + elseif (TxInfo_Step == 2) then + DSM_sendTxSubtrim_21(portNo) - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_21(#%d DATA=TX: 0x21 0x06 %02X %02X %02X %02X)\n", curLine, - data[curLine+1][1], data[curLine+1][2], data[curLine+1][3], data[curLine+1][4]) -- DATA part + Waiting_RX = 0 -- keep Transmitig + if (TxInfo_Type == 0x00) then + TxInfo_Step = 5 -- End Step + else + TxInfo_Step = 3 end - DSM_send(0x21, 0x06, data[curLine+1][1], data[curLine+1][2], data[curLine+1][3], data[curLine+1][4]) - TxInfo_Step = TxInfo_Step + 1 - Waiting_RX = 0 -- keep Transmitig - elseif (TxInfo_Step == 3 and TxInfo_Type==0x1F) then + elseif (TxInfo_Step == 3) then -- 24,6: 0 83 5A B5 - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_24(#%d DATA=TX: 0x24 0x06 %02X %02X %02X %02X)\n", curLine, + if (DEBUG_ON) then LOG_write("CALL DSM_TxInfo_24(#%d DATA=0x24 0x06 %02X %02X %02X %02X)\n", portNo, 0x00, 0x83, 0x5A, 0xB5) -- DATA part end - DSM_send(0x24, 0x06, 0x00, 0x83, 0x5A, 0xB5) - TxInfo_Step = TxInfo_Step + 1 + DSM_send(0x24, 0x06, 0x00, 0x83, 0x5A, 0xB5) -- Still Uknown + TxInfo_Step = 4 Waiting_RX = 0 -- keep Transmitig - elseif (TxInfo_Step == 4 and TxInfo_Type==0x1F) then + elseif (TxInfo_Step == 4) then -- 24,6: 6 80 25 4B - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_24(#%d DATA=TX: 0x24 0x06 %02X %02X %02X %02X)\n", curLine, + if (DEBUG_ON) then LOG_write("CALL DSM_TxInfo_24(#%d DATA=0x24 0x06 %02X %02X %02X %02X)\n", portNo, 0x06, 0x80, 0x25, 0x4B) -- DATA part end - DSM_send(0x24, 0x06, 0x06, 0x80, 0x25, 0x4B) - TxInfo_Step = TxInfo_Step + 1 + DSM_send(0x24, 0x06, 0x06, 0x80, 0x25, 0x4B) -- Still Uknown + TxInfo_Step = 5 Waiting_RX = 0 -- keep Transmitig - elseif (TxInfo_Step == 5 and TxInfo_Type==0x1F) then + elseif (TxInfo_Step == 5) then -- 22,4: 0 0 - if (DEBUG_ON) then LOG_write("CALL DSM_SendTxInfo_22(#%d DATA=TX: 0x22 0x04 %02X %02X)\n", curLine, + if (DEBUG_ON) then LOG_write("CALL DSM_TxInfo_End_22(#%d DATA=%02X %02X)\n", portNo, 0x00, 0x00) -- DATA part end DSM_send(0x22, 0x04, 0x00, 0x00) - TxInfo_Step = TxInfo_Step + 1 + TxInfo_Step = 6 end end @@ -917,13 +1093,13 @@ local function DSM_parseReqTxInfo() -- 0x09 0x05 0x01 0x01 0x00 0x00 0x00 0x00 0x07 Menu: MAIN MENU -- 0x09 0x05 0x01 0x1F 0x00 0x00 0x00 0x00 0x07 Menu: First Time Setup -- Line ?? ???? - local curLine = multiBuffer(12) + local portNo = multiBuffer(12) TxInfo_Type = multiBuffer(13) - if (DEBUG_ON) then LOG_write("RESPONSE ReqTXInfo(LineNum=%d DataType=0x%0X DATA=%s)\n", curLine, TxInfo_Type, multiBuffer2String()) end + if (DEBUG_ON) then LOG_write("RESPONSE ReqTXChannelInfo(#%d DataType=0x%0X DATA=%s)\n", portNo, TxInfo_Type, multiBuffer2String()) end TxInfo_Step = 0 - return curLine + return portNo end @@ -1001,9 +1177,9 @@ local function DSM_processResponse() ctx.Phase = PHASE.MENU_VALUES elseif cmd == 0x05 then -- Request TX Info - local lineNum = DSM_parseReqTxInfo() + local portNo = DSM_parseReqTxInfo() - if (lineNum==ctx.CurLine) then + if (portNo==ctx.CurLine) then -- WEIRD BEHAVIOR -- We got the same line we already got. thi will continue -- on a loop and disconnect RX @@ -1011,7 +1187,7 @@ local function DSM_processResponse() if (DEBUG_ON) then LOG_write("ERROR: Received Same menu line\n") end end -- Got the next line.. keep requesting more - ctx.CurLine = lineNum + ctx.CurLine = portNo ctx.Phase = PHASE.MENU_REQ_TX_INFO elseif cmd == 0xA7 then -- answer to EXIT command @@ -1139,6 +1315,7 @@ local function DSM_Init(toolName) RxName[RX.AR10360T] = "AR10360T" RxName[RX.AR631] = "AR631" + DSM_ReadTxModelData() end local function DSM_Init_Text(rxId) @@ -1250,6 +1427,7 @@ local function DSM_Init_Text(rxId) Text[0x0078] = "FM Channel" if (rxId ~= RX.FC6250HX) then List_Values[0x0078]=channelValues end --FC6250HX uses other range + Text[0x007F] = "Attitude Gain" -- AR636B Text[0x0080] = "Orientation" Text[0x0082] = "Heading" Text[0x0085] = "Frame Rate" @@ -1371,7 +1549,7 @@ local function DSM_Init_Text(rxId) Text[0x010A] = "" -- empty?? Text[0x010B] = "" -- empty?? - Text[0x0190] = "Warning! Relearn Servo Settings" + Text[0x0190] = "Relearn Model/Servo Settings (TX->RX)" Text[0x019C] = "Enter Receiver Bind Mode" Text[0x01D7] = "SAFE Select Channel" Text[0x01DC] = "AS3X/c/b" -- Subtitle, Center+bold @@ -1543,6 +1721,7 @@ Lib.PHASE = PHASE Lib.LINE_TYPE = LINE_TYPE Lib.RX = RX Lib.DISP_ATTR = DISP_ATTR +Lib.CH_TYPE = CH_TYPE Lib.BACK_BUTTON = BACK_BUTTON Lib.NEXT_BUTTON = NEXT_BUTTON @@ -1551,6 +1730,7 @@ Lib.MAX_MENU_LINES = MAX_MENU_LINES -- Export Shared Context Variables Lib.DSM_Context = DSM_Context +Lib.MODEL = MODEL -- Export Functions Lib.LOG_write = LOG_write @@ -1564,6 +1744,7 @@ Lib.phase2String = phase2String Lib.lineValue2String = lineValue2String Lib.menu2String = menu2String Lib.menuLine2String = menuLine2String +Lib.channelType2String = channelType2String Lib.isSelectableLine = isSelectableLine Lib.isEditableLine = isEditableLine @@ -1589,4 +1770,6 @@ Lib.Send_Receive = DSM_Send_Receive Lib.Init = DSM_Init Lib.Init_Text = DSM_Init_Text +Lib.SetDSMChannelInfo = DSM_SetDSMChannelInfo + return Lib diff --git a/Lua_scripts/DSMLIB/DsmFwPrgSIMLib.lua b/Lua_scripts/DSMLIB/DsmFwPrgSIMLib.lua index 22683e4..b66c212 100644 --- a/Lua_scripts/DSMLIB/DsmFwPrgSIMLib.lua +++ b/Lua_scripts/DSMLIB/DsmFwPrgSIMLib.lua @@ -848,7 +848,7 @@ local function AR631_loadMenu(menuId) --L[#3 T=LM VId=0x1003 Text="SAFE"[0xDA] val=0 NL=(0->0,0,S=1) [1->1,1] MId=0x105C ] --L[#6 T=LM VId=0x1006 Text="SAFE Select"[0x1F9] val=0 NL=(0->1,1,S=1) [1->2,1] MId=0x105C ] - ctx.Menu = { MenuId = 0x105C, TextId = 0x1DE, PrevId = 0, NextId = 0, BackId = 0x1010 } + ctx.Menu = { MenuId = 0x105C, TextId = 0x01F9, PrevId = 0, NextId = 0, BackId = 0x1010 } ctx.MenuLines[0] = { Type = LINE_TYPE.VALUE_NUM_I8_NC, TextId = 0x8001, ValId = 0x1000, Min=0, Max=10, Def=0, Val=1 } ctx.MenuLines[1] = { Type = LINE_TYPE.LIST_MENU, TextId = 0x1D7, ValId = 0x1001, Min=53, Max=85, Def=53, Val=5 } ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU, TextId = 0x1DC, ValId = 0x1002, Min=1, Max=2, Def=1, Val=1 } @@ -1338,7 +1338,6 @@ local function loadMenu(menuId) ctx.MenuLines[0] = { MenuId = 0x1000, Type = LINE_TYPE.MENU, Text = "AR630/631/637 (NEW)", ValId = 0x1001,TextId=0 } ctx.MenuLines[1] = { MenuId = 0x1000, Type = LINE_TYPE.MENU, Text = "AR630/631/637 (INITIALIZED)", ValId = 0x1002, TextId=0 } ctx.MenuLines[4] = { MenuId = 0x1000, Type = LINE_TYPE.MENU, Text = "FC6250HX", ValId = 0x1005, TextId=0 } - ctx.MenuLines[6] = { MenuId = 0x1000, Type = LINE_TYPE.MENU, Text = "EXIT Sim to Real RX", ValId = 0xFFFF, TextId=0 } -- Menu 0xFFFF to Exit Simulator ctx.SelLine = 0 lastGoodMenu = menuId diff --git a/Lua_scripts/DSMLIB/DsmSetupLib.lua b/Lua_scripts/DSMLIB/DsmSetupLib.lua new file mode 100644 index 0000000..38b9288 --- /dev/null +++ b/Lua_scripts/DSMLIB/DsmSetupLib.lua @@ -0,0 +1,1074 @@ +---- ######################################################################### +---- # # +---- # 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. # +---- # # +---- ######################################################################### + +------------------------------------------------------------------------------ +-- This scrip does the airplane Setup similar to how a a Spektrum radio does +-- it. You can select the plane type, the Wing type, etc. +-- This settings are needed for ForwardProgramming to send the TX aircraft +-- configuration to the RX when in Initial Setup +-- Author: Francisco Arzu +------------------------------------------------------------------------------ + + +local DEBUG_ON, SIMULATION_ON = ... -- Get DebugON from parameters + +local SETUP_LIB_VERSION = "0.51" +local DATA_PATH = "/SCRIPTS/TOOLS/DSMLIB/data/" -- Path to store model settings files +local dsmLib = assert(loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua"))(DEBUG_ON) + +local PHASE = dsmLib.PHASE +local LINE_TYPE = dsmLib.LINE_TYPE +local CH_TYPE = dsmLib.CH_TYPE +local MODEL = dsmLib.MODEL + +local AIRCRAFT_TYPE = { + PLANE = 0, + HELI = 1, + GLIDER = 2, + DRONE = 3 +} +local aircraft_type_text = {[0]="Plane","Heli","Glider","Drone"} + +local WING_TYPE = { + AIL_1 = 0, --1 + AIL_2 = 1, --2 + FLAPERON = 2, --2 + AIL_1_FLP_1 = 3, --2 + AIL_2_FLP_1 = 4, --3 + AIL_2_FLP_2 = 5, --4 + ELEVON_A = 6, --2 + ELEVON_B = 7 --2 +} +local wing_type_text = {[0]="Normal","Dual Ail","Flapperon", "Ail + Flp","Dual Ail + Flp","Dual Ail/Flp","Elevon A","Elevon B"} + +local TAIL_TYPE = { + RUD_1 = 0, -- 1 + RUD_1_ELEV_1 = 1, -- 2 + RUD_1_ELEV_2 = 2, -- 3 + RUD_2_ELEV_1 = 3, -- 3 + RUD_2_ELEV_2 = 4, -- 4 + VTAIL_A = 5, -- 2 + VTAIL_B = 6, -- 2 + TRAILERON_A = 7, -- 3 + TRAILERON_B = 8, -- 3 +} +local tail_type_text = {[0]="Rud Only","Normal","Rud + Dual Ele","Dual Rud + Elv","Dual Rud/Ele","VTail A","VTail B","Traileron A","Traileron B"} + +local CH_MODE_TYPE = { + NORMAL = 0, + REVERSE = 1, + USE_TX = 3 +} + +local PORT = { + PORT1 = 0, + PORT2 = 1, + PORT3 = 2, + PORT4 = 3, + PORT5 = 4, + PORT6 = 5, + PORT7 = 6, + PORT8 = 7, + PORT9 = 8, + PORT10 = 9, +} + +local MEMU_VAR = { + AIRCRAFT_TYPE = 1001, + WING_TYPE = 1002, + TAIL_TYPE = 1003, + + CH_BASE = 1010, + CH_THR = 1010, + + CH_L_AIL = 1011, + CH_R_AIL = 1012, + CH_L_FLP = 1013, + CH_R_FLP = 1014, + + CH_L_RUD = 1015, + CH_R_RUD = 1016, + CH_L_ELE = 1017, + CH_R_ELE = 1018, + + PORT_BASE = 1020, + PORT1_MODE = 1020, + PORT2_MODE = 1021, + PORT3_MODE = 1022, + PORT4_MODE = 1023, + PORT5_MODE = 1024, + PORT6_MODE = 1025, + PORT7_MODE = 1026, + PORT8_MODE = 1027, + PORT9_MODE = 1028, + PORT10_MODE = 1019, +} + +local SetupLib = {} + +-- MENU DATA Management +local MENU_DATA = {} -- Store the variables used in the Menus. +local menuDataChanged = false -- Flag to notify if any data has changed +local currAircraftType = -1 -- Current AircraftType selected, and to detect change +local currTailType = -1 -- Current WingType selected, and to detect change +local currWingType = -1 -- Current TailType selected, and to detect change + +local lastGoodMenu=0 + +------------------- Model Setup Helper functions ---------------------- + +local function printChannelSummary() + -- Summary + print("Aircraft:".. (aircraft_type_text[currAircraftType] or "--")) + print("Wing Type:".. (wing_type_text[currWingType] or "--")) + print("Tail Type:".. (tail_type_text[currTailType] or "--")) + print("Thr:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_THR] or 30)] or "--")) + print("LAil:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_AIL] or 30)] or "--")) + print("RAil:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_AIL] or 30)] or "--")) + print("LFlp:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_FLP] or 30)] or "--")) + print("RFlp:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_FLP] or 30)] or "--")) + print("LEle:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_ELE] or 30)] or "--")) + print("REle:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_ELE] or 30)] or "--")) + print("LRud:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_RUD] or 30)] or "--")) + print("RRud:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_RUD] or 30)] or "--")) +end + +local function ST_PlaneWingInit(wingType) + print("Change Plane WingType:"..wing_type_text[wingType]) + + currWingType = wingType + + MENU_DATA[MEMU_VAR.WING_TYPE] = wingType + + -- Clear all Wing Data + MENU_DATA[MEMU_VAR.CH_L_AIL] = nil + MENU_DATA[MEMU_VAR.CH_R_AIL] = nil + MENU_DATA[MEMU_VAR.CH_L_FLP] = nil + MENU_DATA[MEMU_VAR.CH_R_FLP] = nil + + MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT1 + + -- Default Channel Assisgments for each Wing type + + if (wingType==WING_TYPE.AIL_1) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2 + elseif (wingType==WING_TYPE.AIL_2) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + elseif (wingType==WING_TYPE.FLAPERON) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + elseif (wingType==WING_TYPE.AIL_1_FLP_1) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT6 + elseif (wingType==WING_TYPE.AIL_2_FLP_1) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5 + elseif (wingType==WING_TYPE.AIL_2_FLP_2) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT7 + elseif (wingType==WING_TYPE.ELEVON_A) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT3 + elseif (wingType==WING_TYPE.ELEVON_B) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + else -- Assume normal + print("ERROR: Invalid Wing Type") + end + + + printChannelSummary() +end + +local function ST_PlaneTailInit(tailType) + if (MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_A) then + tailType = TAIL_TYPE.RUD_1 -- Delta only have ruder + end + + print("Change Plane Tail Type:"..tail_type_text[tailType]) + + currTailType = tailType + + -- Clear all data for Tail + MENU_DATA[MEMU_VAR.TAIL_TYPE] = tailType + MENU_DATA[MEMU_VAR.CH_L_ELE] = nil + MENU_DATA[MEMU_VAR.CH_R_ELE] = nil + MENU_DATA[MEMU_VAR.CH_L_RUD] = nil + MENU_DATA[MEMU_VAR.CH_R_RUD] = nil + + -- Setup Channels for different Tail types + if (tailType == TAIL_TYPE.RUD_1) then + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.RUD_1_ELEV_1) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.RUD_1_ELEV_2) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.RUD_2_ELEV_1) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.RUD_2_ELEV_2) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT6 + MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.VTAIL_A) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT4 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3 + elseif (tailType == TAIL_TYPE.VTAIL_B) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.TRAILERON_A) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3 + elseif (tailType == TAIL_TYPE.TRAILERON_B) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3 + else -- Assume Normal + print("ERROR:invalid Tail Type") + end + + printChannelSummary() +end + +local function ST_GliderWingInit(wingType) + print("Change Glider WingType:"..wing_type_text[wingType]) + + currWingType = wingType + + MENU_DATA[MEMU_VAR.WING_TYPE] = wingType + + -- Clear all Wing Data + MENU_DATA[MEMU_VAR.CH_L_AIL] = nil + MENU_DATA[MEMU_VAR.CH_R_AIL] = nil + MENU_DATA[MEMU_VAR.CH_L_FLP] = nil + MENU_DATA[MEMU_VAR.CH_R_FLP] = nil + MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT6 + + -- Default Channel Assisgments for each Wing type + + if (wingType==WING_TYPE.AIL_1) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1 + elseif (wingType==WING_TYPE.AIL_2) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + elseif (wingType==WING_TYPE.AIL_2_FLP_1) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5 + elseif (wingType==WING_TYPE.AIL_2_FLP_2) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5 + MENU_DATA[MEMU_VAR.CH_R_FLP] = PORT.PORT6 + MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT7 + elseif (wingType==WING_TYPE.ELEVON_A) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2 + elseif (wingType==WING_TYPE.ELEVON_B) then + MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2 + MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT1 + else -- Assume normal + print("ERROR: Invalid Wing Type") + end + + printChannelSummary() +end + +local function ST_GliderTailInit(tailType) + if (MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_A) then + tailType = TAIL_TYPE.RUD_1 -- Delta only have ruder + end + + print("Change Glider Tail Type:"..tail_type_text[tailType]) + + currTailType = tailType + + -- Clear all data for Tail + MENU_DATA[MEMU_VAR.TAIL_TYPE] = tailType + MENU_DATA[MEMU_VAR.CH_L_ELE] = nil + MENU_DATA[MEMU_VAR.CH_R_ELE] = nil + MENU_DATA[MEMU_VAR.CH_L_RUD] = nil + MENU_DATA[MEMU_VAR.CH_R_RUD] = nil + + -- Setup Channels for different Tail types + if (tailType == TAIL_TYPE.RUD_1) then + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.RUD_1_ELEV_1) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4 + elseif (tailType == TAIL_TYPE.VTAIL_A) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT4 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3 + elseif (tailType == TAIL_TYPE.VTAIL_B) then + MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3 + MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT4 + else -- Assume Normal + print("ERROR: Invalid Tail Type") + end + + printChannelSummary() +end + + +local function ST_AircraftInit(aircraftType) + MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE] = aircraftType + currAircraftType = aircraftType + + print("Change Aircraft:".. aircraft_type_text[aircraftType]) + + -- Setup Default Aircraft Wing/Tail + if (aircraftType==AIRCRAFT_TYPE.PLANE) then + ST_PlaneWingInit(WING_TYPE.AIL_1) + ST_PlaneTailInit(TAIL_TYPE.RUD_1_ELEV_1) + elseif (aircraftType==AIRCRAFT_TYPE.GLIDER) then + ST_GliderWingInit(WING_TYPE.AIL_1) + ST_GliderTailInit(TAIL_TYPE.RUD_1_ELEV_1) + else + ST_PlaneWingInit(WING_TYPE.AIL_1) + ST_PlaneTailInit(TAIL_TYPE.RUD_1_ELEV_1) + end + + +end + + +-- Setup Initial Default Data for the Menus +local function ST_Default_Data() + print("Initializing Menu DATA") + ST_AircraftInit(AIRCRAFT_TYPE.PLANE) + + MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT1 + + MENU_DATA[MEMU_VAR.PORT1_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT1].revert + MENU_DATA[MEMU_VAR.PORT2_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT2].revert + MENU_DATA[MEMU_VAR.PORT3_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT3].revert + MENU_DATA[MEMU_VAR.PORT4_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT4].revert + MENU_DATA[MEMU_VAR.PORT5_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT5].revert + MENU_DATA[MEMU_VAR.PORT6_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT6].revert + MENU_DATA[MEMU_VAR.PORT7_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT7].revert + MENU_DATA[MEMU_VAR.PORT8_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT8].revert + MENU_DATA[MEMU_VAR.PORT9_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT9].revert + MENU_DATA[MEMU_VAR.PORT10_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT10].revert +end + +----------------------- FILE MANAGEMENT --------------------------------------------- +-- Create a fairly unique name for a model..combination of name and a hash +-- TODO: Check with ETX why we can't get the filename used to store the model info +-- Improvement request?? + +local function hashName(mName) + local c=10000; + + local prefix = string.gsub(mName,"%.","_") -- Change any "." to "_" + prefix = string.gsub(prefix,"% ","_") -- Change any space to "_" + prefix = string.sub(prefix,1,5) -- Take the first 5 characters + + -- Simple Hash of the Model Name adding each character + for i = 1, #mName do + local ch = string.byte(mName,i,i) + c=c+ch + end + + return (prefix .. c) -- Return Prefix + Hash +end + +-- Load Menu Data from a file +function ST_LoadFileData() + local fname = hashName(MODEL.modelName)..".txt" + + print("Loading File:"..fname) + + local dataFile = io.open(DATA_PATH .. fname, "r") -- read File + -- cannot read file??? + if (dataFile==nil) then return 0 end + + local line = io.read(dataFile, 5000) + io.close(dataFile) + + if #line == 0 then return 0 end -- No data?? + + -- Process the input, each line is "Var_Id : Value" format + -- Store it into MANU_DATA + local i=0 + for k, v in string.gmatch(line, "(%d+):(%d+)") do + --print(string.format("Read MENU_DATA[%d]:[%d]",k, v)) + MENU_DATA[k+0]=v+0 -- do aritmentic to convert string to number + i=i+1 + end + + -- Get the basic info + currAircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE] + currWingType = MENU_DATA[MEMU_VAR.WING_TYPE] + currTailType = MENU_DATA[MEMU_VAR.TAIL_TYPE] + + print("Validation") + print(string.format("AIRCRAFT_TYPE(%d)=%s", MEMU_VAR.AIRCRAFT_TYPE,aircraft_type_text[currAircraftType])) + print(string.format("WING_TYPE(%d)=%s", MEMU_VAR.WING_TYPE, wing_type_text[currWingType])) + print(string.format("TAIL_TYPE(%d)=%s", MEMU_VAR.TAIL_TYPE, tail_type_text[currTailType])) + + printChannelSummary() + + -- No need to save right now + menuDataChanged = false + + -- Return 0 if no lines processed, 1 otherwise + if (i > 0) then return 1 else return 0 end +end + +-- Saves MENU_DATA to a file +function ST_SaveFileData() + local fname = hashName(MODEL.modelName)..".txt" + + print("Saving File:"..fname) + local dataFile = io.open(DATA_PATH .. fname, "w") -- write File + + -- Foreach MENU_DATA with a value write Var_Id:Value into file + for i = 0, MEMU_VAR.PORT10_MODE do + if (MENU_DATA[i]~=nil) then + --print(string.format("Write MENU_DATA[%s] : %s",i,MENU_DATA[i])) + io.write(dataFile,string.format("%s:%s\n",i,MENU_DATA[i])) + end + end + io.close(dataFile) + menuDataChanged = false +end + +-- This Creates the Servo Settings that will be used to pass to +-- Forward programming +local function CreateDSMPortChannelInfo() + local function ApplyWingMixA(b2) + -- ELEVON + if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return 0x20 end; -- 0x03 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.REVERSE) then return 0x50 end; -- 0x23 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return 0x00 end; -- 0x83 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x70 end; -- 0xA3 + end + + local function ApplyTailMixA(b2) + -- VTAIL + if (b2==CH_TYPE.RUD+CH_TYPE.ELE) then return 0x00 end; -- 0x06 + if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.REVERSE) then return 0x70 end; -- 0x26 + if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE) then return 0x20 end; -- 0x86 + if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x50 end; -- 0xA6 + + --TRAILERON + if (b2==CH_TYPE.AIL) then return 0x00 end; -- 0x01 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return 0x00 end; -- 0x03 + if (b2==CH_TYPE.AIL+CH_TYPE.REVERSE) then return 0x70 end; -- 0x21 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.REVERSE) then return 0x70 end; -- 0x23 + if (b2==CH_TYPE.AIL+CH_TYPE.SLAVE) then return 0x00 end; -- 0x81 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return 0x10 end; -- 0x83 + if (b2==CH_TYPE.AIL+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x70 end; -- 0xA1 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x60 end; -- 0xA3 + + end + + local function ApplyWingMixB(b2) + -- ELEVON + if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return 0x00 end; -- 0x03 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.REVERSE) then return 0x70 end; -- 0x23 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return 0x20 end; -- 0x83 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x50 end; -- 0xA3 + end + + local function ApplyTailMixB(b2) + -- VTAIL + if (b2==CH_TYPE.RUD+CH_TYPE.ELE) then return 0x00 end; -- 0x06 + if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.REVERSE) then return 0x70 end; -- 0x26 + if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE) then return 0x40 end; -- 0x86 + if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x30 end; -- 0xA6 + + --TAILERON + if (b2==CH_TYPE.AIL) then return 0x00 end; -- 0x01 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return 0x10 end; -- 0x03 + if (b2==CH_TYPE.AIL+CH_TYPE.REVERSE) then return 0x70 end; -- 0x21 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.REVERSE) then return 0x60 end; -- 0x23 + if (b2==CH_TYPE.AIL+CH_TYPE.SLAVE) then return 0x00 end; -- 0x81 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return 0x00 end; -- 0x83 + if (b2==CH_TYPE.AIL+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x70 end; -- 0xA1 + if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE+CH_TYPE.REVERSE) then return 0x70 end; -- 0xA3 + end + + + + local DSM_ChannelInfo = {} + + for i=0, 9 do + DSM_ChannelInfo[i] = {[0]= 0x00, CH_TYPE.NONE} -- Initialize with no special function + end + + local wingType = MENU_DATA[MEMU_VAR.WING_TYPE] + local tailType = MENU_DATA[MEMU_VAR.TAIL_TYPE] + + local thrCh = MENU_DATA[MEMU_VAR.CH_THR] + local lAilCh = MENU_DATA[MEMU_VAR.CH_L_AIL] + local rAilCh = MENU_DATA[MEMU_VAR.CH_R_AIL] + local lflapCh = MENU_DATA[MEMU_VAR.CH_L_FLP] + local rflapCh = MENU_DATA[MEMU_VAR.CH_R_FLP] + + local lElevCh = MENU_DATA[MEMU_VAR.CH_L_ELE] + local rElevCh = MENU_DATA[MEMU_VAR.CH_R_ELE] + + local lRudCh = MENU_DATA[MEMU_VAR.CH_L_RUD] + local rRudCh = MENU_DATA[MEMU_VAR.CH_R_RUD] + + -- Channels in menu vars are Zero base, Channel info is 1 based + + -- THR + if (thrCh~=nil) then DSM_ChannelInfo[thrCh][1]= CH_TYPE.THR end + + -- AIL (Left and Right) + if (lAilCh~=nil) then DSM_ChannelInfo[lAilCh][1] = CH_TYPE.AIL end + if (rAilCh~=nil) then DSM_ChannelInfo[rAilCh][1] = CH_TYPE.AIL+CH_TYPE.SLAVE end + -- ELE (Left and Right) + if (lElevCh~=nil) then DSM_ChannelInfo[lElevCh][1] = CH_TYPE.ELE end + if (rElevCh~=nil) then DSM_ChannelInfo[rElevCh][1] = CH_TYPE.ELE+CH_TYPE.SLAVE end + -- RUD (Left and Right) + if (lRudCh~=nil) then DSM_ChannelInfo[lRudCh][1] = CH_TYPE.RUD end + if (rRudCh~=nil) then DSM_ChannelInfo[rRudCh][1] = CH_TYPE.RUD+CH_TYPE.SLAVE end + + -- VTAIL: RUD + ELE + if (tailType==TAIL_TYPE.VTAIL_A) then + DSM_ChannelInfo[lElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE + DSM_ChannelInfo[rElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE + elseif (tailType==TAIL_TYPE.VTAIL_B) then + DSM_ChannelInfo[lElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE + DSM_ChannelInfo[rElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE + end + + -- TRAILERRON: 2-ELE + AIL + if (tailType==TAIL_TYPE.TRAILERON_A) then + DSM_ChannelInfo[lElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE + DSM_ChannelInfo[rElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE + elseif (tailType==TAIL_TYPE.TRAILERON_B) then + DSM_ChannelInfo[lElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE + DSM_ChannelInfo[rElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE + end + + ---- ELEVON : AIL + ELE + if (wingType==WING_TYPE.ELEVON_A) then + DSM_ChannelInfo[lAilCh][1] = CH_TYPE.AIL+CH_TYPE.ELE + DSM_ChannelInfo[rAilCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE + elseif (wingType==WING_TYPE.ELEVON_B) then + DSM_ChannelInfo[lAilCh][1] = CH_TYPE.AIL+CH_TYPE.ELE + DSM_ChannelInfo[rAilCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE + end + + -- Apply Gyro Reverse as needed for each channel as long as it is used + for i=0, 9 do + if (MENU_DATA[MEMU_VAR.PORT_BASE+i]==CH_MODE_TYPE.REVERSE and DSM_ChannelInfo[i][1]>0) then + DSM_ChannelInfo[i][1]=DSM_ChannelInfo[i][1]+CH_TYPE.REVERSE + end + end + + -- VTAIL: RUD + ELE + if (tailType==TAIL_TYPE.VTAIL_A) then + DSM_ChannelInfo[lElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[lElevCh][1]) + DSM_ChannelInfo[rElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[rElevCh][1]) + elseif (tailType==TAIL_TYPE.VTAIL_B) then + DSM_ChannelInfo[lElevCh][0] = ApplyTailMixB(DSM_ChannelInfo[lElevCh][1]) + DSM_ChannelInfo[rElevCh][0] = ApplyTailMixB(DSM_ChannelInfo[rElevCh][1]) + end + + -- TRAILERRON: ELE + AIL + if (tailType==TAIL_TYPE.TRAILERON_A) then + if (lAilCh~=nil) then DSM_ChannelInfo[lAilCh][1] = ApplyTailMixA(DSM_ChannelInfo[lAilCh][1]) end + if (rAilCh~=nil) then DSM_ChannelInfo[rAilCh][1] = ApplyTailMixA(DSM_ChannelInfo[rAilCh][1]) end + + DSM_ChannelInfo[lElevCh][1] = ApplyTailMixA(DSM_ChannelInfo[lElevCh][1]) + DSM_ChannelInfo[rElevCh][1] = ApplyTailMixA(DSM_ChannelInfo[rElevCh][1]) + elseif (tailType==TAIL_TYPE.TRAILERON_B) then + if (lAilCh~=nil) then DSM_ChannelInfo[lAilCh][1] = ApplyTailMixB(DSM_ChannelInfo[lAilCh][1]) end + if (rAilCh~=nil) then DSM_ChannelInfo[rAilCh][1] = ApplyTailMixB(DSM_ChannelInfo[rAilCh][1]) end + + DSM_ChannelInfo[lElevCh][1] = ApplyTailMixB(DSM_ChannelInfo[lElevCh][1]) + DSM_ChannelInfo[rElevCh][1] = ApplyTailMixB(DSM_ChannelInfo[rElevCh][1]) + end + + ---- ELEVON : AIL + ELE + if (wingType==WING_TYPE.ELEVON_A) then + DSM_ChannelInfo[lAilCh][0] = ApplyWinglMixA(DSM_ChannelInfo[lAilCh][1]) + DSM_ChannelInfo[rAilCh][0] = ApplyWingMixA(DSM_ChannelInfo[rAilCh][1]) + elseif (wingType==WING_TYPE.ELEVON_B) then + DSM_ChannelInfo[lAilCh][0] = ApplyWingMixB(DSM_ChannelInfo[lAilCh][1]) + DSM_ChannelInfo[rAilCh][0] = ApplyWingMixB(DSM_ChannelInfo[rAilCh][1]) + end + + -- Show how it looks + for i=0, 9 do + local b1,b2 = DSM_ChannelInfo[i][0], DSM_ChannelInfo[i][1] + print(string.format("%s (%02X %02X) %s", MODEL.PORT_TEXT[i], + b1, b2, dsmLib.channelType2String(b1,b2))) + end + + return DSM_ChannelInfo, string.format("Aircraft(%s) Wing(%s) Tail(%s)",aircraft_type_text[currAircraftType],wing_type_text[wingType],tail_type_text[tailType]) +end + +---- Memu Processing Helpers to Mimic the DSM RX menu behaviour + +local function ST_StartConnection() + return 0 +end + +local function ST_ReleaseConnection() +end + +-- Clear each line of the menu +local function clearMenuLines() + local ctx = dsmLib.DSM_Context + for i = 0, dsmLib.MAX_MENU_LINES do -- clear menu + ctx.MenuLines[i] = { MenuId = 0, lineNum = 0, Type = 0, Text = "", TextId = 0, ValId = 0, Min=0, Max=0, Def=0, TextStart=0, Val=nil } + end +end + +-- Post processing needed for each menu +local function PostProcessMenu() + local ctx = dsmLib.DSM_Context + + if (ctx.Menu.Text==nil) then + ctx.Menu.Text = dsmLib.Get_Text(ctx.Menu.TextId) + dsmLib.MenuPostProcessing (ctx.Menu) + end + + if (DEBUG_ON) then dsmLib.LOG_write("SIM RESPONSE Menu: %s\n", dsmLib.menu2String(ctx.Menu)) end + + for i = 0, dsmLib.MAX_MENU_LINES do -- clear menu + local line = ctx.MenuLines[i] + if (line.Type~=0) then + line.MenuId = ctx.Menu.MenuId + line.lineNum = i + dsmLib.MenuLinePostProcessing(line) -- Do the same post processing as if they come from the RX + if (DEBUG_ON) then dsmLib.LOG_write("SIM RESPONSE MenuLine: %s\n", dsmLib.menuLine2String(line)) end + end + + end +end + +-- Creates the menus to Render with the GUI +local function ST_LoadMenu(menuId) + local ctx = dsmLib.DSM_Context + + local function formatTXRevert(port) + return ((MODEL.modelOutputChannel[port].revert==0 and "(Tx:Normal)") or "(Tx:Reverted)") + end + + clearMenuLines() + + if (menuId==0x1000) then -- MAIN MENU + ctx.Menu = { MenuId = 0x1000, Text = "Main Menu ("..MODEL.modelName..")", PrevId = 0, NextId = 0, BackId = 0, TextId=0 } + ctx.MenuLines[0] = { Type = LINE_TYPE.MENU, Text = "Model Setup", ValId = 0x1001,TextId=0 } + + if (menuDataChanged) then + ctx.MenuLines[4] = { Type = LINE_TYPE.MENU, Text="Save Changes", TextId = 0, ValId = 0x1005 } + ctx.MenuLines[5] = { Type = LINE_TYPE.MENU, Text="Discart Changes", TextId = 0, ValId = 0x1006 } + ctx.SelLine = 4 + else + if (SIMULATION_ON) then + ctx.MenuLines[4] = { Type = LINE_TYPE.MENU, Text = "RX Simulator (GUI dev only)", ValId = 0xFFF1, TextId=0 } -- Menu 0xFFF2 to SIMULATOR + end + ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text = "Forward Programming RX", ValId = 0xFFF2, TextId=0 } -- Menu 0xFFF2 to Real RX + ctx.SelLine = 6 + end + lastGoodMenu = menuId + elseif (menuId==0x1001) then -- MODEL SETUP + ctx.Menu = { MenuId = 0x1001, Text = "Model Setup ("..MODEL.modelName..")", PrevId = 0, NextId = 0, BackId = 0x1000, TextId=0 } + ctx.MenuLines[0] = { Type = LINE_TYPE.MENU, Text = "Aircraft Type Setup", ValId = 0x1010,TextId=0 } + ctx.MenuLines[1] = { Type = LINE_TYPE.MENU, Text = "Wing & Tail Channels ", ValId = 0x1020, TextId=0 } + ctx.MenuLines[3] = { Type = LINE_TYPE.MENU, Text = "Gyro Channel Reverse", ValId = 0x1030, TextId=0 } + ctx.MenuLines[5] = { Type = LINE_TYPE.MENU, Text = "WARNING: Changing of Aircraft or Wing will", ValId = 0x1001, TextId=0 } + ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text = "delete previous Channel/Port assigments.", ValId = 0x1001, TextId=0 } + + ctx.SelLine = 0 + lastGoodMenu = menuId + elseif (menuId==0x1005) then + printChannelSummary() + ST_SaveFileData() + + + local msg1 = "Data saved to: " + local msg2 = DATA_PATH..hashName(MODEL.modelName)..".txt" + + ctx.Menu = { MenuId = 0x1005, Text = "Config Saved", PrevId = 0, NextId = 0, BackId = 0, TextId=0 } + ctx.MenuLines[2] = { Type = LINE_TYPE.MENU, Text=msg1, TextId = 0, ValId = 0x1005 } + ctx.MenuLines[3] = { Type = LINE_TYPE.MENU, Text=msg2, TextId = 0, ValId = 0x1005 } + ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text="Complete", TextId = 0, ValId = 0x1000 } + ctx.SelLine = 6 + lastGoodMenu = menuId + elseif (menuId==0x1006) then + ST_LoadFileData() + local msg1 = "Data restored from: " + local msg2 = DATA_PATH..hashName(MODEL.modelName)..".txt" + + ctx.Menu = { MenuId = 0x1006, Text = "Discart Changes", PrevId = 0, NextId = 0, BackId = 0, TextId=0 } + ctx.MenuLines[2] = { Type = LINE_TYPE.MENU, Text=msg1, TextId = 0, ValId = 0x1006 } + ctx.MenuLines[3] = { Type = LINE_TYPE.MENU, Text=msg2, TextId = 0, ValId = 0x1006 } + ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text="Complete", TextId = 0, ValId = 0x1000 } + ctx.SelLine = 6 + lastGoodMenu = menuId + elseif (menuId==0x1010) then + ctx.Menu = { MenuId = 0x1010, Text = "Aircraft Type", PrevId = 0x1001, NextId = 0x1011, BackId = 0, TextId=0 } + ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text="Aircraft Type", TextId = 0, ValId = MEMU_VAR.AIRCRAFT_TYPE, Min=50, Max=53, Def=50, Val=MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE] } + ctx.SelLine = 5 + lastGoodMenu = menuId + elseif (menuId==0x1011) then + ctx.Menu = { MenuId = 0x1011, Text = "Model Type:"..aircraft_type_text[currAircraftType], PrevId = 0x1010, NextId = 0x1020, BackId = 0, TextId=0 } + ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text="Wing Type", TextId = 0, ValId = MEMU_VAR.WING_TYPE, Min=100, Max=107, Def=100, Val=MENU_DATA[MEMU_VAR.WING_TYPE] } + ctx.MenuLines[6] = { Type = LINE_TYPE.LIST_MENU_NC, Text="Tail Type", TextId = 0, ValId = MEMU_VAR.TAIL_TYPE, Min=200, Max=208, Def=200, Val=MENU_DATA[MEMU_VAR.TAIL_TYPE] } + ctx.SelLine = 5 + lastGoodMenu = menuId + elseif (menuId==0x1020) then + ------ WING SETUP ------- + local thr = MENU_DATA[MEMU_VAR.CH_THR] + local leftAil = MENU_DATA[MEMU_VAR.CH_L_AIL] + local rightAil = MENU_DATA[MEMU_VAR.CH_R_AIL] + local leftFlap = MENU_DATA[MEMU_VAR.CH_L_FLP] + local rightFlap = MENU_DATA[MEMU_VAR.CH_R_FLP] + + local thrText = "Thr" + local leftAilText = "Left Aileron" + local rightAilText = "Right Aileron" + 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[currAircraftType].." Wing:"..wing_type_text[currWingType] + + ctx.Menu = { MenuId = 0x1020, Text = title, PrevId = 0x1011, NextId = 0x1021, BackId = 0, TextId=0 } + + ctx.MenuLines[0] = { Type = LINE_TYPE.LIST_MENU_NC, Text=thrText, TextId = 0, ValId = MEMU_VAR.CH_THR, Min=0, Max=9, Def=0, Val= thr } + + ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftAilText, TextId = 0, ValId = MEMU_VAR.CH_L_AIL, Min=0, Max=9, Def=0, Val= leftAil } + + if (rightAil~=nil) then + ctx.MenuLines[3] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightAilText, TextId = 0, ValId = MEMU_VAR.CH_R_AIL, Min=0, Max=9, Def=0, Val= rightAil } + end + + if (leftFlap~=nil) then + ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftFlapText, TextId = 0, ValId = MEMU_VAR.CH_L_FLP, Min=0, Max=9, Def=0, Val= leftFlap } + end + if (rightFlap~=nil) then + ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightFlapText, TextId = 0, ValId = MEMU_VAR.CH_L_FLP, Min=0, Max=9, Def=0, Val= leftFlap } + end + + ctx.SelLine = 1 + lastGoodMenu = menuId + + elseif (menuId==0x1021) then + ------ TAIL SETUP ------- + local leftRud = MENU_DATA[MEMU_VAR.CH_L_RUD] + local rightRud = MENU_DATA[MEMU_VAR.CH_R_RUD] + local leftEle = MENU_DATA[MEMU_VAR.CH_L_ELE] + local rightEle = MENU_DATA[MEMU_VAR.CH_R_ELE] + + local leftRudText = "Left Rudder" + local rightRudText = "Right Rudder" + + local leftElvText = "Left Elevator" + local rightElvText = "Right Elevator" + + if (rightRud==nil) then leftRudText = "Rudder" end + if (rightEle==nil) then leftElvText = "Elevator" end + + local title = aircraft_type_text[currAircraftType].." Tail:"..tail_type_text[currTailType] + + ctx.Menu = { MenuId = 0x1021, Text = title, PrevId = 0x1020, NextId = 0x1001, BackId = 0, TextId=0 } + if (leftRud~=nil) then + ctx.MenuLines[1] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftRudText, TextId = 0, ValId = MEMU_VAR.CH_L_RUD, Min=0, Max=9, Def=0, Val= leftRud} + end + + if (rightRud~=nil) then + ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightRudText, TextId = 0, ValId = MEMU_VAR.CH_R_RUD, Min=0, Max=9, Def=0, Val=rightRud } + end + + if (leftEle~=nil) then + ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftElvText, TextId = 0, ValId = MEMU_VAR.CH_L_ELE, Min=0, Max=9, Def=0, Val=leftEle } + end + + if (rightEle~=nil) then + ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightElvText, TextId = 0, ValId = MEMU_VAR.CH_R_ELE, Min=0, Max=9, Def=0, Val=rightEle } + end + + ctx.SelLine = 1 + lastGoodMenu = menuId + + elseif (menuId==0x1030) then + printChannelSummary() + ctx.Menu = { MenuId = 0x1030, Text = "Gyro Channel Reverse (Needed? not saved yet)", PrevId = 0, NextId = 0, BackId = 0x1001, TextId=0 } + ctx.MenuLines[0] = { Type = LINE_TYPE.LIST_MENU_NC, Text=MODEL.PORT_TEXT[PORT.PORT1], TextId = 0, ValId = MEMU_VAR.PORT1_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT1_MODE], Format = formatTXRevert(PORT.PORT1) } + ctx.MenuLines[1] = { Type = LINE_TYPE.LIST_MENU_NC, Text=MODEL.PORT_TEXT[PORT.PORT2], TextId = 0, ValId = MEMU_VAR.PORT2_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT2_MODE], Format = formatTXRevert(PORT.PORT2) } + ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=MODEL.PORT_TEXT[PORT.PORT3], TextId = 0, ValId = MEMU_VAR.PORT3_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT3_MODE], Format = formatTXRevert(PORT.PORT3) } + ctx.MenuLines[3] = { Type = LINE_TYPE.LIST_MENU_NC, Text=MODEL.PORT_TEXT[PORT.PORT4], TextId = 0, ValId = MEMU_VAR.PORT4_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT4_MODE], Format = formatTXRevert(PORT.PORT4) } + ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=MODEL.PORT_TEXT[PORT.PORT5], TextId = 0, ValId = MEMU_VAR.PORT5_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT5_MODE], Format = formatTXRevert(PORT.PORT5) } + ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text=MODEL.PORT_TEXT[PORT.PORT6], TextId = 0, ValId = MEMU_VAR.PORT6_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT6_MODE], Format = formatTXRevert(PORT.PORT6) } + + ctx.SelLine = 0 + lastGoodMenu = menuId + else + print("NOT IMPLEMENTED") + ctx.Menu = { MenuId = 0x0002, Text = "NOT IMPLEMENTED", TextId = 0, PrevId = 0, NextId = 0, BackId = lastGoodMenu } + ctx.SelLine = dsmLib.BACK_BUTTON + end + + PostProcessMenu() +end + +-- ST_SendReceive +-- Main state machine for the Setup menu + +local function ST_SendReceive() + local ctx = dsmLib.DSM_Context + --if (DEBUG_ON) then dsmLib.LOG_write("%3.3f %s: ", dsmLib.getElapsedTime(), dsmLib.phase2String(ctx.Phase)) end + + if ctx.Phase == PHASE.RX_VERSION then -- request RX version + ctx.RX.Name = "MODEL SETUP" + ctx.RX.Version = SETUP_LIB_VERSION + ctx.Phase = PHASE.MENU_TITLE + + ctx.Refresh_Display = true + + + elseif ctx.Phase == PHASE.WAIT_CMD then + + elseif ctx.Phase == PHASE.MENU_TITLE then -- request menu title + if ctx.Menu.MenuId == 0 then -- First time loading a menu ? + ST_LoadMenu(0x01000) + else + ST_LoadMenu(ctx.Menu.MenuId) + end + ctx.Phase = PHASE.WAIT_CMD + ctx.Refresh_Display = true + + elseif ctx.Phase == PHASE.VALUE_CHANGING then -- send value + local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line + + if (MENU_DATA[line.ValId] ~= line.Val ) then + MENU_DATA[line.ValId] = line.Val + print(string.format("MENU_DATA[%d/%s]=%d",line.ValId,line.Text, line.Val)) + menuDataChanged=true + end + + ctx.Phase = PHASE.VALUE_CHANGING_WAIT + + elseif ctx.Phase == PHASE.VALUE_CHANGING_WAIT then + local line = ctx.MenuLines[ctx.SelLine] + + elseif ctx.Phase == PHASE.VALUE_CHANGE_END then -- send value + local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line + + -- Update the menu data from the line + if (MENU_DATA[line.ValId] ~= line.Val ) then + MENU_DATA[line.ValId] = line.Val + print(string.format("MENU_DATA[%d/%s]=%d",line.ValId,line.Text, line.Val)) + menuDataChanged=true + end + + -- Did the aircraft type change? + if (currAircraftType ~= MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]) then + ST_AircraftInit(MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]) + end + + -- Did the Wing type change? + if (currWingType ~= MENU_DATA[MEMU_VAR.WING_TYPE]) then + if (currAircraftType==AIRCRAFT_TYPE.GLIDER) then + ST_GliderWingInit(MENU_DATA[MEMU_VAR.WING_TYPE]) + else + ST_PlaneWingInit(MENU_DATA[MEMU_VAR.WING_TYPE]) + end + + -- DELTA has only RUDER + if ((currWingType==WING_TYPE.ELEVON_A or currWingType==WING_TYPE.ELEVON_B) and TAIL_TYPE~=TAIL_TYPE.RUD_1) then + currTailType = TAIL_TYPE.RUD_1 + end + end + + --- Did the tail changed? + if (currTailType ~= MENU_DATA[MEMU_VAR.TAIL_TYPE]) then + if (currAircraftType==AIRCRAFT_TYPE.GLIDER) then + ST_GliderTailInit(MENU_DATA[MEMU_VAR.TAIL_TYPE]) + else + ST_PlaneTailInit(MENU_DATA[MEMU_VAR.TAIL_TYPE]) + end + end + + ctx.Phase = PHASE.WAIT_CMD + elseif ctx.Phase == PHASE.EXIT then + ctx.Phase=PHASE.EXIT_DONE + end +end + +------------------------------------------------------------------------------------------------------------ +-- TEXT Management + +local List_Text = {} +local Text = {} +local List_Text_Img = {} +local List_Values = {} + +-- Get the text for this menus +local function ST_Get_Text(index) + local out = Text[index] -- Find in regular header first + if out== nil then + out = List_Text[index] -- Try list values, don't think is necesary, but just playing Safe + end + if out == nil then -- unknown... + out = "Unknown_" .. string.format("%X", index) + end + return out +end + +-- Get the List text for this menus +local function ST_Get_List_Text(index) + local out = List_Text[index] -- Try to find the message in List_Text + if out == nil then + out = Text[index] -- Try list headers, don't think is necesary, but just playing Safe + end + if out == nil then -- unknown... + out = "UnknownLT_" .. string.format("%X", index) + end + return out +end + +-- Get the List_Text Images +local function ST_Get_List_Text_Img(index) + local out = List_Text_Img[index] + return out +end + +local function ST_Get_List_Values(index) + local out = List_Values[index] + return out +end + +-- Inital List and Image Text for this menus +local function ST_Init_Text(rxId) + dsmLib.Init_Text(rxId) + + -- Channel Names use the Port Text Retrived from OTX/ETX + for i = 0, 9 do List_Text[i] = MODEL.PORT_TEXT[i] end + + -- Aircraft Type + List_Text[50+AIRCRAFT_TYPE.PLANE] = "Airplane"; --List_Text_Img[50+AIRCRAFT_TYPE.PLANE] = "at_plane.png|Airplane" + List_Text[50+AIRCRAFT_TYPE.GLIDER] = "Glider (Partial work)"; --List_Text_Img[50+AIRCRAFT_TYPE.GLIDER] = "at_glider.png|Glider" + List_Text[50+AIRCRAFT_TYPE.HELI] = "Helicopter (Not done)"; --List_Text_Img[50+AIRCRAFT_TYPE.HELI] = "at_heli.png|Helicopter" + List_Text[50+AIRCRAFT_TYPE.DRONE] = "Drone (not done)"; --List_Text_Img[50+AIRCRAFT_TYPE.DRONE] = "at_drone.png|Drone" + + -- Wing Types + List_Text[100+WING_TYPE.AIL_1] = "Single Ail"; List_Text_Img[100+WING_TYPE.AIL_1] = "wt_1ail.png|Single Aileron" + List_Text[100+WING_TYPE.AIL_2] = "Dual Ail"; List_Text_Img[100+WING_TYPE.AIL_2] = "wt_2ail.png|Dual Aileron" + List_Text[100+WING_TYPE.FLAPERON] = "Flaperon"; List_Text_Img[100+WING_TYPE.FLAPERON] = "wt_flaperon.png|Flaperon" + List_Text[100+WING_TYPE.AIL_1_FLP_1] = "Ail + Flap"; List_Text_Img[100+WING_TYPE.AIL_1_FLP_1] = "wt_1ail_1flp.png|Aileron + Flap" + List_Text[100+WING_TYPE.AIL_2_FLP_1] = "Dual Ail + Flap"; List_Text_Img[100+WING_TYPE.AIL_2_FLP_1] = "wt_2ail_1flp.png|Dual Aileron + Flap" + List_Text[100+WING_TYPE.AIL_2_FLP_2] = "Dual Ail + Dual Flap"; List_Text_Img[100+WING_TYPE.AIL_2_FLP_2] = "wt_2ail_2flp.png|Dual Aileron + Dual Flap" + List_Text[100+WING_TYPE.ELEVON_A] = "Delta/Elevon A"; List_Text_Img[100+WING_TYPE.ELEVON_A] = "wt_elevon.png|Delta/Elevon A" + List_Text[100+WING_TYPE.ELEVON_B] = "Delta/Elevon B"; List_Text_Img[100+WING_TYPE.ELEVON_B] = "wt_elevon.png|Delta/Elevon B" + + -- Tail Types + List_Text[200+TAIL_TYPE.RUD_1] = "Rudder Only"; List_Text_Img[200+TAIL_TYPE.RUD_1] = "tt_1rud.png|Rudder Only" + List_Text[200+TAIL_TYPE.RUD_1_ELEV_1] = "Rud + Ele"; List_Text_Img[200+TAIL_TYPE.RUD_1_ELEV_1] = "tt_1rud_1ele.png|Tail Normal" + List_Text[200+TAIL_TYPE.RUD_1_ELEV_2] = "Rud + Dual Ele"; List_Text_Img[200+TAIL_TYPE.RUD_1_ELEV_2] = "tt_1rud_2ele.png|Rud + Dual Elev" + List_Text[200+TAIL_TYPE.RUD_2_ELEV_1] = "Dual Rud + Ele"; List_Text_Img[200+TAIL_TYPE.RUD_2_ELEV_1] = "tt_2rud_1ele.png|Dual Rud + Elev" + List_Text[200+TAIL_TYPE.RUD_2_ELEV_2] = "Dual Rud + Dual Ele"; List_Text_Img[200+TAIL_TYPE.RUD_2_ELEV_2] = "tt_2rud_2ele.png|Dual Rud + Dual Elev" + List_Text[200+TAIL_TYPE.VTAIL_A] = "V-Tail A"; List_Text_Img[200+TAIL_TYPE.VTAIL_A] = "tt_vtail.png|V-Tail A" + List_Text[200+TAIL_TYPE.VTAIL_B] = "V-Tail B"; List_Text_Img[200+TAIL_TYPE.VTAIL_B] = "tt_vtail.png|V-Tail B" + List_Text[200+TAIL_TYPE.TRAILERON_A] = "Traileron A"; List_Text_Img[200+TAIL_TYPE.TRAILERON_A] = "tt_traileron.png|Traileron A" + List_Text[200+TAIL_TYPE.TRAILERON_B] = "Traileron B"; List_Text_Img[200+TAIL_TYPE.TRAILERON_B] = "tt_traileron.png|Traileron B" + + -- Servo Reverse + List_Text[300+CH_MODE_TYPE.NORMAL] = "Normal " + List_Text[300+CH_MODE_TYPE.REVERSE] = "Reverted" + +end + +-- Initial Setup +local function ST_Init() + -- Initialize dsmLib background + dsmLib.Init() + -- Initialize text (use RX_ID 0) + ST_Init_Text(0) + + -- Setup default Data, and load a file if exist + ST_Default_Data() + if (ST_LoadFileData()==0) then -- Did not load a file + ST_SaveFileData() -- Save Defaults + end +end + + +------------------------------------------------------------------------------------------------------------ +-- Lib EXPORTS + +-- Export Constants +SetupLib.PHASE = dsmLib.PHASE +SetupLib.LINE_TYPE = dsmLib.LINE_TYPE +SetupLib.RX = dsmLib.RX +SetupLib.DISP_ATTR = dsmLib.DISP_ATTR + +SetupLib.BACK_BUTTON = dsmLib.BACK_BUTTON +SetupLib.NEXT_BUTTON = dsmLib.NEXT_BUTTON +SetupLib.PREV_BUTTON = dsmLib.PREV_BUTTON +SetupLib.MAX_MENU_LINES = dsmLib.MAX_MENU_LINES + +-- Export Shared Context Variables +SetupLib.DSM_Context = dsmLib.DSM_Context + +-- Export Functions +SetupLib.LOG_write = dsmLib.LOG_write +SetupLib.LOG_close = dsmLib.LOG_close +SetupLib.getElapsedTime = dsmLib.getElapsedTime + +SetupLib.Get_Text = ST_Get_Text +SetupLib.Get_List_Text = ST_Get_List_Text +SetupLib.Get_List_Text_Img = ST_Get_List_Text_Img + +SetupLib.phase2String = dsmLib.phase2String +SetupLib.menu2String = dsmLib.menu2String +SetupLib.menuLine2String = dsmLib.menuLine2String + +SetupLib.isSelectableLine = dsmLib.isSelectableLine +SetupLib.isEditableLine = dsmLib.isEditableLine +SetupLib.isListLine = dsmLib.isListLine +SetupLib.isPercentValueLine = dsmLib.isPercentValueLine +SetupLib.isNumberValueLine = dsmLib.isNumberValueLine +SetupLib.isDisplayAttr = dsmLib.isDisplayAttr +SetupLib.isFlightModeLine = dsmLib.isFlightModeLine +SetupLib.GetFlightModeValue = dsmLib.GetFlightModeValue + +SetupLib.StartConnection = ST_StartConnection -- Override Function +SetupLib.ReleaseConnection = ST_ReleaseConnection -- Override Function +SetupLib.ChangePhase = dsmLib.ChangePhase +SetupLib.Value_Add = dsmLib.Value_Add +SetupLib.Value_Default = dsmLib.Value_Default +SetupLib.Value_Write_Validate = dsmLib.Value_Write_Validate +SetupLib.GotoMenu = dsmLib.GotoMenu +SetupLib.MoveSelectionLine = dsmLib.MoveSelectionLine +SetupLib.Send_Receive = ST_SendReceive -- Override Function +SetupLib.Init = ST_Init +SetupLib.Init_Text = ST_Init_Text + +SetupLib.CreateDSMPortChannelInfo = CreateDSMPortChannelInfo + +return SetupLib diff --git a/Lua_scripts/DSMLIB/data/readme.txt b/Lua_scripts/DSMLIB/data/readme.txt new file mode 100644 index 0000000..5469dc1 --- /dev/null +++ b/Lua_scripts/DSMLIB/data/readme.txt @@ -0,0 +1,7 @@ +This directory contains the DSM Forward programming settings +for each model. Like Wing Type, Tail Type, and Channels assignments. + +The name is the first 5 characters of the model and a hash number to make them unique. + +If you want to REDO a model from scratch, just delete the file or change the Aircraft type to reset. + diff --git a/Lua_scripts/DSMLIB/img/tt_1rud.png b/Lua_scripts/DSMLIB/img/tt_1rud.png new file mode 100644 index 0000000..e5c3684 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_1rud.png differ diff --git a/Lua_scripts/DSMLIB/img/tt_1rud_1ele.png b/Lua_scripts/DSMLIB/img/tt_1rud_1ele.png new file mode 100644 index 0000000..5546a25 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_1rud_1ele.png differ diff --git a/Lua_scripts/DSMLIB/img/tt_1rud_2ele.png b/Lua_scripts/DSMLIB/img/tt_1rud_2ele.png new file mode 100644 index 0000000..cbf22a3 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_1rud_2ele.png differ diff --git a/Lua_scripts/DSMLIB/img/tt_2rud_1ele.png b/Lua_scripts/DSMLIB/img/tt_2rud_1ele.png new file mode 100644 index 0000000..a059219 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_2rud_1ele.png differ diff --git a/Lua_scripts/DSMLIB/img/tt_2rud_2ele.png b/Lua_scripts/DSMLIB/img/tt_2rud_2ele.png new file mode 100644 index 0000000..c679d3b Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_2rud_2ele.png differ diff --git a/Lua_scripts/DSMLIB/img/tt_traileron.png b/Lua_scripts/DSMLIB/img/tt_traileron.png new file mode 100644 index 0000000..cbf22a3 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_traileron.png differ diff --git a/Lua_scripts/DSMLIB/img/tt_vtail.png b/Lua_scripts/DSMLIB/img/tt_vtail.png new file mode 100644 index 0000000..e8d1c08 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/tt_vtail.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_1ail.png b/Lua_scripts/DSMLIB/img/wt_1ail.png new file mode 100644 index 0000000..1611053 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_1ail.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_1ail_1flp.png b/Lua_scripts/DSMLIB/img/wt_1ail_1flp.png new file mode 100644 index 0000000..b51d1fd Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_1ail_1flp.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_2ail.png b/Lua_scripts/DSMLIB/img/wt_2ail.png new file mode 100644 index 0000000..95686ff Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_2ail.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_2ail_1flp.png b/Lua_scripts/DSMLIB/img/wt_2ail_1flp.png new file mode 100644 index 0000000..5b13f6c Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_2ail_1flp.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_2ail_2flp.png b/Lua_scripts/DSMLIB/img/wt_2ail_2flp.png new file mode 100644 index 0000000..87b3842 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_2ail_2flp.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_elevon.png b/Lua_scripts/DSMLIB/img/wt_elevon.png new file mode 100644 index 0000000..fa354ca Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_elevon.png differ diff --git a/Lua_scripts/DSMLIB/img/wt_flaperon.png b/Lua_scripts/DSMLIB/img/wt_flaperon.png new file mode 100644 index 0000000..82d2464 Binary files /dev/null and b/Lua_scripts/DSMLIB/img/wt_flaperon.png differ diff --git a/Lua_scripts/DSMLIB/readme.md b/Lua_scripts/DSMLIB/readme.md index 1a27f2f..44ddab9 100644 --- a/Lua_scripts/DSMLIB/readme.md +++ b/Lua_scripts/DSMLIB/readme.md @@ -10,8 +10,9 @@ Script. The goal was to make it easier to understand, mantain, and to separate the GUI from the DSM Forward programming engine/logic. In this way, GUIs can evolve independent. Color/Touch Gui, Text only GUI, etc. -Most of the changes has been cometic, but fixed a few operational ones -1. Make "Gyro Settings"->"Initial Setup" works (Tested on AR631,AR637xx) +Changes and fixes +1. Menus to be able to configure Plane in a similar way as Spektrum Radio +1. Make "Gyro Settings"->"Initial Setup" works (Tested on AR631,AR637xx with PLANE type of arcraft) 2. Properly reset and restart after initial configuration and SAFE changes. 3. Write Log of the conversation between RX/TX. To be use for debugging when some reports a problem. 4. Provide a simulation of RX to do GUI development in Companion, and undestand patterns of how the data is organized. @@ -25,12 +26,10 @@ Since is RX and Menu specific, we cannot create a general hack. Please report of you have test it with other receivers to update the documentation. -If you get `"Unable to Load menu lines"` when trying to navidate to a menu, could be that the code needs to be specially adapter to mandle that menu in a different way than others. We did that HACK for AR631/AR637 for the `Initial Setup` and `Initial Safe Setup` menus. Before starting the script again, the problem shouls show at the log. Usually not been able to process some `Unknown_0x5` lines who has not been fully reversed engineered (you can share the logs with us to try to understand what is going on. - # Flight mode/Gain channels I ran into a case where trying to set Aux2 or Aux3 for flight mode, but the RX was correcting it to Aux1.. the RX only was allowing Gear or Aux1 (AR631/AR637). -This is because the RX don't know that we are using more than 6 channels. To make the RX aware that there are other channels, while edditing the channel, you have to toggle the switch to excersist the channel, and now the RX will recognize it. +This is because the RX don't know that we are using more than 6 channels. To make the RX aware that there are other channels, while edditing the channel, you have to toggle the switch to excersist the channel (3 times), and now the RX will recognize it. # Deployment @@ -38,9 +37,11 @@ This is because the RX don't know that we are using more than 6 channels. To mak /SCRIPTS/TOOLS/DsmFwdPrg_05_Color.lua -- Color+touch radios /SCRIPTS/TOOLS/DSMLIB/ -- (ALL CAPITALS) Libraries ane extra files /SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua -- DSM Protocol Message and Menu engine - SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lua -- Simulation of AR631, FC6250HX - SCRIPTS/TOOLS/DSMLIB/img --Images for RX orientations - LOGS/dsm_log.txt --Readable log of the last RX/TX session, usefull for debuging new RX + /SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lua -- Simulation of AR631, FC6250HX + /SCRIPTS/TOOLS/DSMLIB/SetupLib.lua -- Model Setup Screns + /SCRIPTS/TOOLS/DSMLIB/img --Images for RX orientations + /SCRIPTS/TOOLS/DSMLIB/data --Data of model config (Wing Type, Servo Assigments) + /LOGS/dsm_log.txt --Readable log of the last RX/TX session, usefull for debuging new RX # Messages Displayed in the GUI @@ -111,22 +112,11 @@ Exmple of the Unknown_0x05 Lines correctly processed (receiving lines 0..5): 0.700 MENU_UNKNOWN_LINES: RESPONSE MenuUknownLine_0x05: LineNum=2 DATA=RX: 09 05 02 01 00 00 00 07 00 00 00 00 00 00 00 00 0.760 MENU_UNKNOWN_LINES: CALL DSM_getNextUknownLine_0x05(LastLine=2) -Example when it will not be able to load the menu (gets stuck in line 0). -After nor advancing on the lines, it will show in the UI as `"Unable to load menu lines"` - - 0.280 MENU_LINES: SEND DSM_getFirstMenuLine(MenuId=0x1022) - 0.400 MENU_LINES: RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 00 01 00 00 00 07 00 00 00 00 00 00 00 00 - 0.460 MENU_UNKNOWN_LINES: CALL DSM_getNextUknownLine_0x05(LastLine=0) - 0.550 MENU_UNKNOWN_LINES: RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 00 01 00 00 00 07 00 00 00 00 00 00 00 00 - 0.600 MENU_UNKNOWN_LINES: CALL DSM_getNextUknownLine_0x05(LastLine=0) - 0.700 MENU_UNKNOWN_LINES: RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 02 00 00 00 00 07 00 00 00 00 00 00 00 00 - 0.760 MENU_UNKNOWN_LINES: CALL DSM_getNextUknownLine_0x05(LastLine=0) - # Validation of data by the RX When you change a value in the GUI, the RX validates that the value is valid. -For example, I ran into a case where trying to set Aux2 or Aux3 for flight mode, but the RX was correcting it to Aux1.. the RX only was allowing Gear or Aux1 (AR631/AR637). +For example, I ran into a case where trying to set Aux2 or Aux3 for flight mode, but the RX was correcting it back to Aux1.. the RX only was allowing Gear or Aux1 (AR631/AR637).. in this case, toggle the Switch while editing it on the screen. If you go to the logs, you can see that the RX was correcting the value: @@ -137,6 +127,16 @@ If you go to the logs, you can see that the RX was correcting the value: --- +# Version 0.51 +- New Screens to Configure Model (Wing Type/Tail Tail, etc) +- Finally got understanding that the previous unknown 0x05 lines are to send Model/Servo data to RX. +- Fix use of AR636B (Firmare version 4.40.0 for Blade 230 heli, is the only one with Forward Programing) +- Aircraft types: Tested With Plane type only.. Glider and other in progress + +### Know Problems: +- 4-Servo Wing type (Dual Ail/Tail) in planes give conflicting servo assignments by defaults.. Solution choose your own Ch. +- Glider, Heli, Drong: Still in development. In glider, only a few wing type works.. needs to restrict menu options for the only valid one. + # Version 0.5