mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-02-04 20:48:12 +00:00
62aa58d32d
1. NEW Black&White Radios new model setup. Now it can setup completely a plane from zero 2. Color version; simplified code for Tail mixes, and fix Taileron setup
790 lines
29 KiB
Lua
790 lines
29 KiB
Lua
|
|
local Log, DEBUG_ON = ...
|
|
|
|
local DATA_PATH = "/MODELS/DSMDATA" -- Path to store model settings files
|
|
local TX_CHANNELS = 12
|
|
|
|
-- MODEL information from ETX/OTX
|
|
local ModelLib = {}
|
|
|
|
local MODEL = {
|
|
modelName = "", -- The name of the model comming from OTX/ETX
|
|
modelOutputChannel = {}, -- Output information from OTX/ETX
|
|
AirWingTailDesc = "",
|
|
|
|
TX_CH_TEXT = {},
|
|
PORT_TEXT = {},
|
|
DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script
|
|
}
|
|
|
|
--Channel Types --
|
|
local CH_TYPE = {
|
|
NONE = 0x00,
|
|
AIL = 0x01,
|
|
ELE = 0x02,
|
|
RUD = 0x04,
|
|
|
|
REVERSE = 0x20,
|
|
THR = 0x40,
|
|
SLAVE = 0x80,
|
|
}
|
|
|
|
-- Seems like Reverse Mix is complement of the 3 bits
|
|
local CH_MIX_TYPE = {
|
|
MIX_NORM = 0x00, -- 0000
|
|
MIX_AIL = 0x10, -- 0001 Taileron
|
|
MIX_ELE = 0x20, -- 0010 For VTIAL and Delta-ELEVON
|
|
MIX_RUD = 0x30, -- 0011 For VTIAL
|
|
|
|
MIX_RUD_REV = 0x40, -- 0100 For VTIAL
|
|
MIX_ELE_REV = 0x50, -- 0101 For VTIAL and Delta-ELEVON A
|
|
MIX_AIL_REV = 0x60, -- 0110 Taileron
|
|
MIX_NORM_REV = 0x70 -- 0111
|
|
}
|
|
|
|
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
|
|
TRAILERON_A_R2 = 9, -- 3
|
|
TRAILERON_B_R2 = 10 -- 3
|
|
}
|
|
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 + 2x Rud","Taileron B + 2x Rud"}
|
|
|
|
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,
|
|
PORT11 = 10,
|
|
PORT12 = 11
|
|
}
|
|
|
|
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 = 1029,
|
|
PORT11_MODE = 1030,
|
|
PORT12_MODE = 1031,
|
|
|
|
DATA_END = 1040
|
|
}
|
|
|
|
|
|
-- MENU DATA Management
|
|
local MENU_DATA = {} -- Store the variables used in the Menus.
|
|
|
|
|
|
---- 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.MIX_NORM, CH_TYPE.THR}, -- Ch1 Thr (0x40)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.AIL}, -- Ch2 Ail (0x01)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.ELE}, -- Ch2 ElE (0x02)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.RUD}, -- Ch4 Rud (0x04)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch5 Gear (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch6 Aux1 (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch7 Aux2 (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch8 Aux3 (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch9 Aux4 (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch10 Aux5 (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch11 Aux6 (0x00)
|
|
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE} -- Ch12 Aux7 (0x00)
|
|
}
|
|
|
|
function ModelLib.printChannelSummary(a,w,t)
|
|
-- Summary
|
|
print("CHANNEL INFORMATION")
|
|
print("Aircraft:".. (aircraft_type_text[MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]] or "--"))
|
|
print("Wing Type:".. (wing_type_text[MENU_DATA[MEMU_VAR.WING_TYPE]] or "--"))
|
|
print("Tail Type:".. (tail_type_text[MENU_DATA[MEMU_VAR.TAIL_TYPE]] or "--"))
|
|
print("Thr:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_THR] or 30)] or "--")) -- use fake ch30 for non existing channels
|
|
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
|
|
|
|
function ModelLib.printServoReverseInfo()
|
|
print("SERVO Normal/Reverse INFORMATION")
|
|
for i=0, TX_CHANNELS-1 do
|
|
local s="--"
|
|
if (MENU_DATA[MEMU_VAR.PORT1_MODE+i] or 0) == 0 then s="NORMAL" else s="REVERSE" end
|
|
print(string.format("Port%d: %s", i+1, s))
|
|
end
|
|
end
|
|
|
|
function ModelLib.channelType2String(byte1, byte2)
|
|
local s = ""
|
|
|
|
if (byte2==0) then return s end;
|
|
|
|
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.REVERSE)>0) then s=s.."-" end
|
|
|
|
if (bit32.band(byte2,CH_TYPE.SLAVE)>0) then s=s.." Slv" end
|
|
|
|
if (byte1==CH_MIX_TYPE.MIX_NORM) then s=s.." "
|
|
elseif (byte1==CH_MIX_TYPE.MIX_AIL) then s=s.." M_Ail"
|
|
elseif (byte1==CH_MIX_TYPE.MIX_ELE) then s=s.." M_Ele"
|
|
elseif (byte1==CH_MIX_TYPE.MIX_RUD) then s=s.." M_Rud"
|
|
elseif (byte1==CH_MIX_TYPE.MIX_RUD_REV) then s=s.." M_Rud-"
|
|
elseif (byte1==CH_MIX_TYPE.MIX_ELE_REV) then s=s.." M_Ele-"
|
|
elseif (byte1==CH_MIX_TYPE.MIX_AIL_REV) then s=s.." M_Ail-"
|
|
elseif (byte1==CH_MIX_TYPE.MIX_NORM_REV) then s=s.." M-"
|
|
end
|
|
|
|
return s;
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- Read the model information from OTX/ETX
|
|
|
|
local function getModuleChannelOrder(num)
|
|
--Determine fist 4 channels order
|
|
local channel_names={}
|
|
local stick_names = {[0]= "R", "E", "T", "A" }
|
|
local ch_order=num
|
|
if (ch_order == -1) then
|
|
channel_names[0] = stick_names[3]
|
|
channel_names[1] = stick_names[1]
|
|
channel_names[2] = stick_names[2]
|
|
channel_names[3] = stick_names[0]
|
|
else
|
|
channel_names[bit32.band(ch_order,3)] = stick_names[3]
|
|
ch_order = math.floor(ch_order/4)
|
|
channel_names[bit32.band(ch_order,3)] = stick_names[1]
|
|
ch_order = math.floor(ch_order/4)
|
|
channel_names[bit32.band(ch_order,3)] = stick_names[2]
|
|
ch_order = math.floor(ch_order/4)
|
|
channel_names[bit32.band(ch_order,3)] = stick_names[0]
|
|
end
|
|
|
|
local s = ""
|
|
for i=0,3 do
|
|
s=s..channel_names[i]
|
|
end
|
|
return s
|
|
end
|
|
|
|
function ModelLib.ReadTxModelData()
|
|
local TRANSLATE_AETR_TO_TAER=false
|
|
local table = model.getInfo() -- Get the model name
|
|
MODEL.modelName = table.name
|
|
|
|
local module = model.getModule(0) -- Internal
|
|
if (module==nil or module.Type~=6) then module = model.getModule(1) end -- External
|
|
if (module~=nil) then
|
|
if (module.Type==6 ) then -- MULTI-MODULE
|
|
local chOrder = module.channelsOrder
|
|
local s = getModuleChannelOrder(chOrder)
|
|
Log.LOG_write("MultiChannel Ch Order: [%s] %s\n",chOrder,s)
|
|
|
|
if (s=="AETR") then TRANSLATE_AETR_TO_TAER=true
|
|
else TRANSLATE_AETR_TO_TAER=false
|
|
end
|
|
end
|
|
end
|
|
|
|
Log.LOG_write("MODEL NAME = %s\n",MODEL.modelName)
|
|
|
|
-- Read Ch1 to Ch10
|
|
local i= 0
|
|
for i = 0, TX_CHANNELS-1 do
|
|
local ch = model.getOutput(i) -- Zero base
|
|
if (ch~=nil) then
|
|
MODEL.modelOutputChannel[i] = ch
|
|
if (string.len(ch.name)==0) then
|
|
ch.formatCh = string.format("TX:Ch%i",i+1)
|
|
else
|
|
ch.formatCh = 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.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.LOG_write("Ports/Channels:\n")
|
|
for i = 0, TX_CHANNELS-1 do
|
|
local ch = MODEL.modelOutputChannel[i]
|
|
if (ch~=nil) then
|
|
MODEL.TX_CH_TEXT[i] = ch.formatCh
|
|
MODEL.PORT_TEXT[i] = string.format("P%i (%s) ",i+1,MODEL.TX_CH_TEXT[i])
|
|
|
|
Log.LOG_write("Port%d %s [%d,%d] Rev=%d, Off=%d, ppmC=%d, syn=%d\n",i+1,MODEL.TX_CH_TEXT[i],math.floor(ch.min/10),math.floor(ch.max/10), ch.revert, ch.offset, ch.ppmCenter, ch.symetrical)
|
|
end
|
|
end
|
|
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??
|
|
|
|
function ModelLib.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 ModelLib.ST_LoadFileData()
|
|
local fname = ModelLib.hashName(MODEL.modelName)..".txt"
|
|
|
|
-- Clear Menu Data
|
|
for i = 0, MEMU_VAR.DATA_END do
|
|
MENU_DATA[i]=nil
|
|
end
|
|
|
|
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
|
|
|
|
local currAircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
|
local currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
|
local 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]))
|
|
|
|
ModelLib.printChannelSummary()
|
|
ModelLib.printServoReverseInfo()
|
|
|
|
-- 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 ModelLib.ST_SaveFileData()
|
|
local fname = ModelLib.hashName(MODEL.modelName)..".txt"
|
|
|
|
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, MEMU_VAR.DATA_END 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)
|
|
end
|
|
|
|
-- This Creates the Servo Settings that will be used to pass to
|
|
-- Forward programming
|
|
function ModelLib.CreateDSMPortChannelInfo()
|
|
local function ApplyWingMixA(b2)
|
|
-- ELEVON
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_ELE end; -- 0x03
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x83
|
|
end
|
|
|
|
local function ApplyWingMixB(b2)
|
|
-- ELEVON
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x03
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_ELE end; -- 0x83
|
|
end
|
|
|
|
local function ApplyTailMixA(b2)
|
|
-- VTAIL
|
|
-- Default normal/reverse behaviour
|
|
if (b2==CH_TYPE.RUD+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x06
|
|
if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_ELE end; -- 0x86
|
|
|
|
--TAILERON
|
|
-- Default normal/reverse behaviour
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x03
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_AIL end; -- 0x83
|
|
end
|
|
|
|
local function ApplyTailMixB(b2)
|
|
-- VTAIL
|
|
-- Default normal/reverse behaviour
|
|
if (b2==CH_TYPE.RUD+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x06
|
|
if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_RUD end; -- 0x86
|
|
|
|
--TAILERON
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_AIL end; -- 0x03
|
|
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x83
|
|
end
|
|
|
|
local function reverseMix(b)
|
|
if (b==CH_MIX_TYPE.MIX_NORM) then return CH_MIX_TYPE.MIX_NORM_REV end;
|
|
if (b==CH_MIX_TYPE.MIX_AIL) then return CH_MIX_TYPE.MIX_AIL_REV end;
|
|
if (b==CH_MIX_TYPE.MIX_ELE) then return CH_MIX_TYPE.MIX_ELE_REV end;
|
|
if (b==CH_MIX_TYPE.MIX_RUD) then return CH_MIX_TYPE.MIX_RUD_REV end;
|
|
return b
|
|
end
|
|
|
|
|
|
|
|
local DSM_ChannelInfo = MODEL.DSM_ChannelInfo
|
|
|
|
for i=0, TX_CHANNELS-1 do
|
|
DSM_ChannelInfo[i] = {[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE} -- Initialize with no special function
|
|
end
|
|
|
|
local aircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
|
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 and thrCh < 10) 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 or tailType==TAIL_TYPE.VTAIL_B) then
|
|
DSM_ChannelInfo[lElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE
|
|
DSM_ChannelInfo[rElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE
|
|
end
|
|
|
|
-- TAILERRON: 2-ELE + AIL
|
|
if (tailType==TAIL_TYPE.TRAILERON_A or tailType==TAIL_TYPE.TRAILERON_A_R2 or
|
|
tailType==TAIL_TYPE.TRAILERON_B or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
|
DSM_ChannelInfo[lElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE
|
|
DSM_ChannelInfo[rElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE
|
|
end
|
|
|
|
---- ELEVON : AIL + ELE
|
|
if (wingType==WING_TYPE.ELEVON_A or 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
|
|
|
|
------MIXES ---------
|
|
|
|
-- TAIL Mixes (Elevator and VTail)
|
|
if (tailType==TAIL_TYPE.VTAIL_A or tailType==TAIL_TYPE.TRAILERON_A or tailType==TAIL_TYPE.TRAILERON_A_R2) 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 or tailType==TAIL_TYPE.TRAILERON_B or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
|
DSM_ChannelInfo[lElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[lElevCh][1])
|
|
DSM_ChannelInfo[rElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[rElevCh][1])
|
|
end
|
|
|
|
---- Wing Mixes
|
|
if (wingType==WING_TYPE.ELEVON_A) then
|
|
DSM_ChannelInfo[lAilCh][0] = ApplyWingMixA(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
|
|
|
|
-- Apply Gyro Reverse as needed for each channel as long as it is used
|
|
for i=0, TX_CHANNELS-1 do
|
|
if (MENU_DATA[MEMU_VAR.PORT_BASE+i]==CH_MODE_TYPE.REVERSE and DSM_ChannelInfo[i][1]>0) then
|
|
DSM_ChannelInfo[i][0]=reverseMix(DSM_ChannelInfo[i][0])
|
|
DSM_ChannelInfo[i][1]=DSM_ChannelInfo[i][1]+CH_TYPE.REVERSE
|
|
end
|
|
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, ModelLib.channelType2String(b1,b2)))
|
|
end
|
|
|
|
MODEL.AirWingTailDesc = string.format("Aircraft(%s) Wing(%s) Tail(%s)",aircraft_type_text[aircraftType],wing_type_text[wingType],tail_type_text[tailType])
|
|
end
|
|
|
|
function ModelLib.ST_PlaneWingInit(wingType)
|
|
print("Change Plane WingType:"..wing_type_text[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_R_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
|
|
|
|
|
|
ModelLib.printChannelSummary()
|
|
end
|
|
|
|
function ModelLib.ST_PlaneTailInit(tailType)
|
|
if (MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_A or
|
|
MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_B) then
|
|
tailType = TAIL_TYPE.RUD_1 -- Delta only have ruder
|
|
end
|
|
|
|
print("Change Plane Tail Type:"..tail_type_text[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.PORT4
|
|
MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT5
|
|
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.PORT4
|
|
MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT6
|
|
elseif (tailType == TAIL_TYPE.VTAIL_A or tailType == TAIL_TYPE.VTAIL_B) then
|
|
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT4
|
|
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3
|
|
elseif (tailType == TAIL_TYPE.TRAILERON_A or tailType==TAIL_TYPE.TRAILERON_A_R2 or
|
|
tailType == TAIL_TYPE.TRAILERON_B or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
|
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
|
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
|
|
|
|
if (tailType == TAIL_TYPE.TRAILERON_A_R2 or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
|
MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT7
|
|
end
|
|
|
|
ModelLib.printChannelSummary()
|
|
end
|
|
|
|
function ModelLib.ST_GliderWingInit(wingType)
|
|
print("Change Glider WingType:"..wing_type_text[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
|
|
|
|
ModelLib.printChannelSummary()
|
|
end
|
|
|
|
function ModelLib.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])
|
|
|
|
-- 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
|
|
|
|
ModelLib.printChannelSummary()
|
|
end
|
|
|
|
|
|
function ModelLib.ST_AircraftInit(aircraftType)
|
|
MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE] = aircraftType
|
|
|
|
print("Change Aircraft:".. aircraft_type_text[aircraftType])
|
|
|
|
-- Setup Default Aircraft Wing/Tail
|
|
if (aircraftType==AIRCRAFT_TYPE.PLANE) then
|
|
ModelLib.ST_PlaneWingInit(WING_TYPE.AIL_1)
|
|
ModelLib.ST_PlaneTailInit(TAIL_TYPE.RUD_1_ELEV_1)
|
|
elseif (aircraftType==AIRCRAFT_TYPE.GLIDER) then
|
|
ModelLib.ST_GliderWingInit(WING_TYPE.AIL_1)
|
|
ModelLib.ST_GliderTailInit(TAIL_TYPE.RUD_1_ELEV_1)
|
|
else
|
|
ModelLib.ST_PlaneWingInit(WING_TYPE.AIL_1)
|
|
ModelLib.ST_PlaneTailInit(TAIL_TYPE.RUD_1_ELEV_1)
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
-- Setup Initial Default Data for the Menus
|
|
function ModelLib.ST_Default_Data()
|
|
print("Initializing Menu DATA")
|
|
ModelLib.ST_AircraftInit(AIRCRAFT_TYPE.PLANE)
|
|
|
|
print("Initializing Servo Reverse from TX output settings")
|
|
|
|
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
|
|
|
|
ModelLib.printServoReverseInfo()
|
|
|
|
end
|
|
|
|
|
|
ModelLib.TX_CHANNELS = TX_CHANNELS
|
|
ModelLib.MODEL = MODEL
|
|
ModelLib.CH_TYPE = CH_TYPE
|
|
ModelLib.CH_MODE_TYPE = CH_MODE_TYPE
|
|
ModelLib.AIRCRAFT_TYPE = AIRCRAFT_TYPE
|
|
ModelLib.WING_TYPE = WING_TYPE
|
|
ModelLib.TAIL_TYPE = TAIL_TYPE
|
|
ModelLib.MENU_DATA = MENU_DATA
|
|
ModelLib.MEMU_VAR = MEMU_VAR
|
|
ModelLib.PORT = PORT
|
|
ModelLib.DATA_PATH = DATA_PATH
|
|
|
|
ModelLib.aircraft_type_text = aircraft_type_text
|
|
ModelLib.wing_type_text = wing_type_text
|
|
ModelLib.tail_type_text = tail_type_text
|
|
|
|
|
|
return ModelLib
|
|
|