SD card is now in own repository at https://github.com/EdgeTX/edgetx-sdcard
Removing this obsolete copy here.
@@ -1 +0,0 @@
|
||||
*/opentx.sdcard.version
|
||||
@@ -1,2 +0,0 @@
|
||||
You can put firmware for your modules or radio in this folder.
|
||||
Files in this folder are NOT automaticaly applied.
|
||||
@@ -1,3 +0,0 @@
|
||||
2.2 : BMP renamed to IMAGES for consistency between Taranis and Horus.
|
||||
You can put your model and other graphic files in this directory.
|
||||
Format include bmp and png (including png with transparancy).
|
||||
@@ -1 +0,0 @@
|
||||
Logs files created by "SD Logs" special function will be stored in this directory.
|
||||
@@ -1 +0,0 @@
|
||||
This directory is for lua functions scripts.
|
||||
@@ -1 +0,0 @@
|
||||
This directory is for lua mixer scripts.
|
||||
@@ -1,121 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
local devices = { }
|
||||
local lineIndex = 1
|
||||
local pageOffset = 0
|
||||
|
||||
local function createDevice(id, name)
|
||||
local device = {
|
||||
id = id,
|
||||
name = name,
|
||||
timeout = 0
|
||||
}
|
||||
return device
|
||||
end
|
||||
|
||||
local function getDevice(name)
|
||||
for i=1, #devices do
|
||||
if devices[i].name == name then
|
||||
return devices[i]
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function parseDeviceInfoMessage(data)
|
||||
local id = data[2]
|
||||
local name = ""
|
||||
local i = 3
|
||||
while data[i] ~= 0 do
|
||||
name = name .. string.char(data[i])
|
||||
i = i + 1
|
||||
end
|
||||
local device = getDevice(name)
|
||||
if device == nil then
|
||||
device = createDevice(id, name)
|
||||
devices[#devices + 1] = device
|
||||
end
|
||||
local time = getTime()
|
||||
device.timeout = time + 3000 -- 30s
|
||||
if lineIndex == 0 then
|
||||
lineIndex = 1
|
||||
end
|
||||
end
|
||||
|
||||
local devicesRefreshTimeout = 0
|
||||
local function refreshNext()
|
||||
local command, data = crossfireTelemetryPop()
|
||||
if command == nil then
|
||||
local time = getTime()
|
||||
if time > devicesRefreshTimeout then
|
||||
devicesRefreshTimeout = time + 100 -- 1s
|
||||
crossfireTelemetryPush(0x28, { 0x00, 0xEA })
|
||||
end
|
||||
elseif command == 0x29 then
|
||||
parseDeviceInfoMessage(data)
|
||||
end
|
||||
end
|
||||
|
||||
local function selectDevice(step)
|
||||
lineIndex = 1 + ((lineIndex + step - 1 + #devices) % #devices)
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
lineIndex = 0
|
||||
pageOffset = 0
|
||||
end
|
||||
|
||||
NoCross = { 110, LCD_H - 28, "Waiting for Crossfire devices...", DEFAULT_COLOR + INVERS + BLINK }
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT then
|
||||
selectDevice(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectDevice(-1)
|
||||
end
|
||||
|
||||
lcd.clear()
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5,"CROSSFIRE SETUP", MENU_COLOR)
|
||||
|
||||
|
||||
if #devices == 0 then
|
||||
lcd.drawText(NoCross[1],NoCross[2],NoCross[3],NoCross[4])
|
||||
else
|
||||
for i=1, #devices do
|
||||
local attr = (lineIndex == i and INVERS or 0)
|
||||
if event == EVT_VIRTUAL_ENTER and attr == INVERS then
|
||||
crossfireTelemetryPush(0x28, { devices[i].id, 0xEA })
|
||||
return "device.lua"
|
||||
end
|
||||
lcd.drawText(5, i*22+10, devices[i].name, attr)
|
||||
end
|
||||
end
|
||||
|
||||
refreshNext()
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
@@ -1,528 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
local deviceId = 0
|
||||
local deviceName = ""
|
||||
local lineIndex = 0
|
||||
local pageOffset = 0
|
||||
local edit = false
|
||||
local charIndex = 1
|
||||
local fieldPopup
|
||||
local fieldTimeout = 0
|
||||
local fieldId = 1
|
||||
local fieldChunk = 0
|
||||
local fieldData = {}
|
||||
local fields = {}
|
||||
|
||||
local function getField(line)
|
||||
local counter = 1
|
||||
for i = 1, #fields do
|
||||
local field = fields[i]
|
||||
if not field.hidden then
|
||||
if counter < line then
|
||||
counter = counter + 1
|
||||
else
|
||||
return field
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function initLineIndex()
|
||||
lineIndex = 0
|
||||
for i = 1, #fields do
|
||||
local field = getField(i)
|
||||
if field and field.type ~= 11 and field.type ~= 12 and field.name ~= nil then
|
||||
lineIndex = i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function incrField(step)
|
||||
local field = getField(lineIndex)
|
||||
if field.type == 10 then
|
||||
local byte = 32
|
||||
if charIndex <= #field.value then
|
||||
byte = string.byte(field.value, charIndex) + step
|
||||
end
|
||||
if byte < 32 then
|
||||
byte = 32
|
||||
elseif byte > 122 then
|
||||
byte = 122
|
||||
end
|
||||
if charIndex <= #field.value then
|
||||
field.value = string.sub(field.value, 1, charIndex-1) .. string.char(byte) .. string.sub(field.value, charIndex+1)
|
||||
else
|
||||
field.value = field.value .. string.char(byte)
|
||||
end
|
||||
else
|
||||
local min, max = 0, 0
|
||||
if ((field.type <= 5) or (field.type == 8)) then
|
||||
min = field.min
|
||||
max = field.max
|
||||
step = field.step * step
|
||||
elseif field.type == 9 then
|
||||
min = 0
|
||||
max = #field.values - 1
|
||||
end
|
||||
if (step < 0 and field.value > min) or (step > 0 and field.value < max) then
|
||||
field.value = field.value + step
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
local newLineIndex = lineIndex
|
||||
local field
|
||||
repeat
|
||||
newLineIndex = newLineIndex + step
|
||||
if newLineIndex == 0 then
|
||||
newLineIndex = #fields
|
||||
elseif newLineIndex == 1 + #fields then
|
||||
newLineIndex = 1
|
||||
pageOffset = 0
|
||||
end
|
||||
field = getField(newLineIndex)
|
||||
until newLineIndex == lineIndex or (field and field.type ~= 11 and field.name)
|
||||
lineIndex = newLineIndex
|
||||
if lineIndex > 11 + pageOffset then -- NOTE: increased from 7 to 11 to allow 11 lines in Horus display
|
||||
pageOffset = lineIndex - 11 -- NOTE: increased from 7 to 11 to allow 11 lines in Horus display
|
||||
elseif lineIndex <= pageOffset then
|
||||
pageOffset = lineIndex - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function split(str)
|
||||
local t = {}
|
||||
local i = 1
|
||||
for s in string.gmatch(str, "([^;]+)") do
|
||||
t[i] = s
|
||||
i = i + 1
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function fieldGetString(data, offset)
|
||||
local result = ""
|
||||
while data[offset] ~= 0 do
|
||||
result = result .. string.char(data[offset])
|
||||
offset = offset + 1
|
||||
end
|
||||
offset = offset + 1
|
||||
return result, offset
|
||||
end
|
||||
|
||||
local function parseDeviceInfoMessage(data)
|
||||
local offset
|
||||
deviceId = data[2]
|
||||
deviceName, offset = fieldGetString(data, 3)
|
||||
local fields_count = data[offset+12]
|
||||
for i=1, fields_count do
|
||||
fields[i] = { name=nil }
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldGetValue(data, offset, size)
|
||||
local result = 0
|
||||
for i=0, size-1 do
|
||||
result = bit32.lshift(result, 8) + data[offset + i]
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function fieldUnsignedLoad(field, data, offset, size)
|
||||
field.value = fieldGetValue(data, offset, size)
|
||||
field.min = fieldGetValue(data, offset+size, size)
|
||||
field.max = fieldGetValue(data, offset+2*size, size)
|
||||
field.default = fieldGetValue(data, offset+3*size, size)
|
||||
field.unit, offset = fieldGetString(data, offset+4*size)
|
||||
field.step = 1
|
||||
end
|
||||
|
||||
local function fieldUnsignedToSigned(field, size)
|
||||
local bandval = bit32.lshift(0x80, (size-1)*8)
|
||||
field.value = field.value - bit32.band(field.value, bandval) * 2
|
||||
field.min = field.min - bit32.band(field.min, bandval) * 2
|
||||
field.max = field.max - bit32.band(field.max, bandval) * 2
|
||||
field.default = field.default - bit32.band(field.default, bandval) * 2
|
||||
end
|
||||
|
||||
local function fieldSignedLoad(field, data, offset, size)
|
||||
fieldUnsignedLoad(field, data, offset, size)
|
||||
fieldUnsignedToSigned(field, size)
|
||||
end
|
||||
|
||||
local function fieldIntSave(index, value, size)
|
||||
local frame = { deviceId, 0xEA, index }
|
||||
for i=size-1, 0, -1 do
|
||||
frame[#frame + 1] = (bit32.rshift(value, 8*i) % 256)
|
||||
end
|
||||
crossfireTelemetryPush(0x2D, frame)
|
||||
end
|
||||
|
||||
local function fieldUnsignedSave(field, size)
|
||||
local value = field.value
|
||||
fieldIntSave(field.id, value, size)
|
||||
end
|
||||
|
||||
local function fieldSignedSave(field, size)
|
||||
local value = field.value
|
||||
if value < 0 then
|
||||
value = bit32.lshift(0x100, (size-1)*8) + value
|
||||
end
|
||||
fieldIntSave(field.id, value, size)
|
||||
end
|
||||
|
||||
local function fieldIntDisplay(field, y, attr)
|
||||
-- lcd.drawNumber(140, y, field.value, LEFT + attr) -- NOTE: original code getLastPos not available in Horus
|
||||
-- lcd.drawText(lcd.getLastPos(), y, field.unit, attr) -- NOTE: original code getLastPos not available in Horus
|
||||
lcd.drawText(140, y, field.value .. field.unit, attr) -- NOTE: Concenated fields instead of get lastPos
|
||||
end
|
||||
|
||||
-- UINT8
|
||||
local function fieldUint8Load(field, data, offset)
|
||||
fieldUnsignedLoad(field, data, offset, 1)
|
||||
end
|
||||
|
||||
local function fieldUint8Save(field)
|
||||
fieldUnsignedSave(field, 1)
|
||||
end
|
||||
|
||||
-- INT8
|
||||
local function fieldInt8Load(field, data, offset)
|
||||
fieldSignedLoad(field, data, offset, 1)
|
||||
end
|
||||
|
||||
local function fieldInt8Save(field)
|
||||
fieldSignedSave(field, 1)
|
||||
end
|
||||
|
||||
-- UINT16
|
||||
local function fieldUint16Load(field, data, offset)
|
||||
fieldUnsignedLoad(field, data, offset, 2)
|
||||
end
|
||||
|
||||
local function fieldUint16Save(field)
|
||||
fieldUnsignedSave(field, 2)
|
||||
end
|
||||
|
||||
-- INT16
|
||||
local function fieldInt16Load(field, data, offset)
|
||||
fieldSignedLoad(field, data, offset, 2)
|
||||
end
|
||||
|
||||
local function fieldInt16Save(field)
|
||||
fieldSignedSave(field, 2)
|
||||
end
|
||||
|
||||
-- FLOAT
|
||||
local function fieldFloatLoad(field, data, offset)
|
||||
field.value = fieldGetValue(data, offset, 4)
|
||||
field.min = fieldGetValue(data, offset+4, 4)
|
||||
field.max = fieldGetValue(data, offset+8, 4)
|
||||
field.default = fieldGetValue(data, offset+12, 4)
|
||||
fieldUnsignedToSigned(field, 4)
|
||||
field.prec = data[offset+16]
|
||||
if field.prec > 3 then
|
||||
field.prec = 3
|
||||
end
|
||||
field.step = fieldGetValue(data, offset+17, 4)
|
||||
field.unit, offset = fieldGetString(data, offset+21)
|
||||
end
|
||||
|
||||
local function formatFloat(num, decimals)
|
||||
local mult = 10^(decimals or 0)
|
||||
local val = num / mult
|
||||
return string.format("%." .. decimals .. "f", val)
|
||||
end
|
||||
|
||||
local function fieldFloatDisplay(field, y, attr)
|
||||
lcd.drawText(140, y, formatFloat(field.value, field.prec) .. field.unit, attr)
|
||||
end
|
||||
|
||||
local function fieldFloatSave(field)
|
||||
fieldUnsignedSave(field, 4)
|
||||
end
|
||||
|
||||
-- TEXT SELECTION
|
||||
local function fieldTextSelectionLoad(field, data, offset)
|
||||
local values
|
||||
values, offset = fieldGetString(data, offset)
|
||||
if values ~= "" then
|
||||
field.values = split(values)
|
||||
end
|
||||
field.value = data[offset]
|
||||
field.min = data[offset+1]
|
||||
field.max = data[offset+2]
|
||||
field.default = data[offset+3]
|
||||
field.unit, offset = fieldGetString(data, offset+4)
|
||||
end
|
||||
|
||||
local function fieldTextSelectionSave(field)
|
||||
crossfireTelemetryPush(0x2D, { deviceId, 0xEA, field.id, field.value })
|
||||
end
|
||||
|
||||
local function fieldTextSelectionDisplay(field, y, attr)
|
||||
-- lcd.drawText(140, y, field.values[field.value+1], attr) -- NOTE: original code getLastPos not available in Horus
|
||||
-- lcd.drawText(lcd.getLastPos(), y, field.unit, attr) -- NOTE: original code getLastPos not available in Horus
|
||||
lcd.drawText(140, y, field.values[field.value+1] .. field.unit, attr) -- NOTE: Concenated fields instead of get lastPos
|
||||
end
|
||||
|
||||
-- STRING
|
||||
local function fieldStringLoad(field, data, offset)
|
||||
field.value, offset = fieldGetString(data, offset)
|
||||
if #data >= offset then
|
||||
field.maxlen = data[offset]
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldStringSave(field)
|
||||
local frame = { deviceId, 0xEA, field.id }
|
||||
for i=1, string.len(field.value) do
|
||||
frame[#frame + 1] = string.byte(field.value, i)
|
||||
end
|
||||
frame[#frame + 1] = 0
|
||||
crossfireTelemetryPush(0x2D, frame)
|
||||
end
|
||||
|
||||
local function fieldStringDisplay(field, y, attr)
|
||||
if edit == true and attr then
|
||||
-- lcd.drawText(140, y, field.value, FIXEDWIDTH) -- NOTE: FIXEDWIDTH unknown....
|
||||
-- lcd.drawText(134+6*charIndex, y, string.sub(field.value, charIndex, charIndex), FIXEDWIDTH + attr) -- NOTE: FIXEDWIDTH unknown....
|
||||
lcd.drawText(140, y, field.value, attr)
|
||||
lcd.drawText(134+6*charIndex, y, string.sub(field.value, charIndex, charIndex), attr)
|
||||
else
|
||||
lcd.drawText(140, y, field.value, attr)
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldCommandLoad(field, data, offset)
|
||||
field.status = data[offset]
|
||||
field.timeout = data[offset+1]
|
||||
field.info, offset = fieldGetString(data, offset+2)
|
||||
if field.status == 0 then
|
||||
fieldPopup = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldCommandSave(field)
|
||||
if field.status == 0 then
|
||||
field.status = 1
|
||||
crossfireTelemetryPush(0x2D, { deviceId, 0xEA, field.id, field.status })
|
||||
fieldPopup = field
|
||||
fieldTimeout = getTime() + field.timeout
|
||||
end
|
||||
end
|
||||
|
||||
local function fieldCommandDisplay(field, y, attr)
|
||||
lcd.drawText(1, y, field.name, attr)
|
||||
if field.info ~= "" then
|
||||
lcd.drawText(140, y, "[" .. field.info .. "]")
|
||||
end
|
||||
end
|
||||
|
||||
local functions = {
|
||||
{ load=fieldUint8Load, save=fieldUint8Save, display=fieldIntDisplay },
|
||||
{ load=fieldInt8Load, save=fieldInt8Save, display=fieldIntDisplay },
|
||||
{ load=fieldUint16Load, save=fieldUint16Save, display=fieldIntDisplay },
|
||||
{ load=fieldInt16Load, save=fieldInt16Save, display=fieldIntDisplay },
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
{ load=fieldFloatLoad, save=fieldFloatSave, display=fieldFloatDisplay },
|
||||
{ load=fieldTextSelectionLoad, save=fieldTextSelectionSave, display=fieldTextSelectionDisplay },
|
||||
{ load=fieldStringLoad, save=fieldStringSave, display=fieldStringDisplay },
|
||||
nil,
|
||||
{ load=fieldStringLoad, save=fieldStringSave, display=fieldStringDisplay },
|
||||
{ load=fieldCommandLoad, save=fieldCommandSave, display=fieldCommandDisplay },
|
||||
}
|
||||
|
||||
local function parseParameterInfoMessage(data)
|
||||
if data[2] ~= deviceId or data[3] ~= fieldId then
|
||||
fieldData = {}
|
||||
fieldChunk = 0
|
||||
return
|
||||
end
|
||||
local field = fields[fieldId]
|
||||
local chunks = data[4]
|
||||
for i=5, #data do
|
||||
fieldData[#fieldData + 1] = data[i]
|
||||
end
|
||||
if chunks > 0 then
|
||||
fieldChunk = fieldChunk + 1
|
||||
else
|
||||
fieldChunk = 0
|
||||
field.id = fieldId
|
||||
field.parent = fieldData[1]
|
||||
field.type = fieldData[2] % 128
|
||||
field.hidden = (bit32.rshift(fieldData[2], 7) == 1)
|
||||
local name, i = fieldGetString(fieldData, 3)
|
||||
if name ~= "" then
|
||||
local indent = ""
|
||||
local parent = field.parent
|
||||
while parent ~= 0 do
|
||||
indent = indent .. " "
|
||||
parent = fields[parent].parent
|
||||
end
|
||||
field.name = indent .. name
|
||||
end
|
||||
if functions[field.type+1] then
|
||||
functions[field.type+1].load(field, fieldData, i)
|
||||
end
|
||||
if not fieldPopup then
|
||||
if lineIndex == 0 and field.hidden ~= true and field.type and field.type ~= 11 and field.type ~= 12 then
|
||||
initLineIndex()
|
||||
end
|
||||
fieldId = 1 + (fieldId % #fields)
|
||||
end
|
||||
fieldData = {}
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshNext()
|
||||
local command, data = crossfireTelemetryPop()
|
||||
if command == nil then
|
||||
local time = getTime()
|
||||
if fieldPopup then
|
||||
if time > fieldTimeout then
|
||||
crossfireTelemetryPush(0x2D, { deviceId, 0xEA, fieldPopup.id, 6 })
|
||||
fieldTimeout = time + fieldPopup.timeout
|
||||
end
|
||||
elseif time > fieldTimeout and not edit then
|
||||
crossfireTelemetryPush(0x2C, { deviceId, 0xEA, fieldId, fieldChunk })
|
||||
fieldTimeout = time + 200 -- 2s
|
||||
end
|
||||
elseif command == 0x29 then
|
||||
parseDeviceInfoMessage(data)
|
||||
elseif command == 0x2B then
|
||||
parseParameterInfoMessage(data)
|
||||
fieldTimeout = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runDevicePage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
if edit == true then
|
||||
edit = false
|
||||
local field = getField(lineIndex)
|
||||
fieldTimeout = getTime() + 200 -- 2s
|
||||
fieldId, fieldChunk = field.id, 0
|
||||
fieldData = {}
|
||||
functions[field.type+1].save(field)
|
||||
else
|
||||
return "crossfire.lua"
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
local field = getField(lineIndex)
|
||||
if field.name then
|
||||
if field.type == 10 then
|
||||
if edit == false then
|
||||
edit = true
|
||||
charIndex = 1
|
||||
else
|
||||
charIndex = charIndex + 1
|
||||
end
|
||||
elseif field.type < 11 then
|
||||
edit = not edit
|
||||
end
|
||||
if edit == false then
|
||||
fieldTimeout = getTime() + 200 -- 2s
|
||||
fieldId, fieldChunk = field.id, 0
|
||||
fieldData = {}
|
||||
functions[field.type+1].save(field)
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
incrField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
incrField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
|
||||
lcd.clear()
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5,deviceName, MENU_COLOR)
|
||||
|
||||
for y = 1, 11 do
|
||||
local field = getField(pageOffset+y)
|
||||
if not field then
|
||||
break
|
||||
elseif field.name == nil then
|
||||
lcd.drawText(1, y*22+10, "...")
|
||||
else
|
||||
local attr = lineIndex == (pageOffset+y) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
lcd.drawText(1, y*22+10, field.name)
|
||||
if functions[field.type+1] then
|
||||
functions[field.type+1].display(field, y*22+10, attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
local function runPopupPage(event)
|
||||
local result
|
||||
if fieldPopup.status == 3 then
|
||||
result = popupConfirmation("Confirmation", fieldPopup.info, event)
|
||||
else
|
||||
result = popupWarning(fieldPopup.info, event)
|
||||
end
|
||||
if result == "OK" then
|
||||
crossfireTelemetryPush(0x2D, { deviceId, 0xEA, fieldPopup.id, 4 })
|
||||
elseif result == "CANCEL" then
|
||||
crossfireTelemetryPush(0x2D, { deviceId, 0xEA, fieldPopup.id, 5 })
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
lineIndex, edit = 0, false
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
end
|
||||
|
||||
local result
|
||||
if fieldPopup ~= nil then
|
||||
result = runPopupPage(event)
|
||||
else
|
||||
result = runDevicePage(event)
|
||||
end
|
||||
|
||||
refreshNext()
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
@@ -1,557 +0,0 @@
|
||||
local toolName = "TNS|DSM Forward Programming|TNE"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
|
||||
--###############################################################################
|
||||
-- Multi buffer for DSM description
|
||||
-- Multi_Buffer[0..2]=="DSM" -> Lua script is running
|
||||
-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent
|
||||
-- Multi_Buffer[4..9]=6 bytes of TX to RX data
|
||||
-- Multi_Buffer[10..25]=16 bytes of RX to TX data
|
||||
--
|
||||
-- To start operation:
|
||||
-- Write 0x00 at address 3
|
||||
-- Write 0x00 at address 10
|
||||
-- Write "DSM" at address 0..2
|
||||
--###############################################################################
|
||||
|
||||
local RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED = 0, 1, 2, 3, 4, 5, 6, 7
|
||||
local MENU, LIST_MENU_NOCHANGING, LIST_MENU2, PERCENTAGE_VALUE = 0x1C, 0x6C, 0x4C, 0xC0
|
||||
local Phase = RX_VERSION
|
||||
local Waiting_RX = 0
|
||||
local Text = {}
|
||||
local Retry=100
|
||||
local Blink = 0
|
||||
local Value_Changed=0
|
||||
|
||||
local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId=nil, Back=nil, BackId=nil, CurLine=nil, SelLine=nil, EditLine=nil }
|
||||
local Line = {}
|
||||
local RX = { Name="", Version="" }
|
||||
|
||||
local function conv_int16(number)
|
||||
if number >= 0x8000 then
|
||||
return number - 0x10000
|
||||
end
|
||||
return number
|
||||
end
|
||||
|
||||
local function Get_Text(index)
|
||||
out = Text[index]
|
||||
if out == nil then -- unknown...
|
||||
out = "Unknown_"..string.format("%X",index)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local function DSM_Release()
|
||||
multiBuffer( 0, 0 )
|
||||
end
|
||||
|
||||
local function DSM_Send(...)
|
||||
local arg = {...}
|
||||
for i = 1 , #arg do
|
||||
multiBuffer( 3+i, arg[i])
|
||||
end
|
||||
multiBuffer( 3, 0x70+#arg)
|
||||
end
|
||||
|
||||
local function Value_Add(dir)
|
||||
local line=Line[Menu.SelLine]
|
||||
Speed = getRotEncSpeed()
|
||||
if Speed == ROTENC_MIDSPEED then
|
||||
line.Val = line.Val + (5 * dir)
|
||||
elseif Speed == ROTENC_HIGHSPEED then
|
||||
line.Val = line.Val + (15 * dir)
|
||||
else
|
||||
line.Val = line.Val + dir
|
||||
end
|
||||
if line.Val > line.Max then
|
||||
line.Val = line.Max
|
||||
elseif line.Val < line.Min then
|
||||
line.Val = line.Min
|
||||
end
|
||||
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
|
||||
Phase = VALUE_CHANGING
|
||||
Waiting_RX = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function DSM_Menu(event)
|
||||
local Speed = 0
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
if Menu.EditLine == nil then
|
||||
-- not changing a value
|
||||
if Menu.SelLine ~= nil then
|
||||
if Menu.SelLine < 7 then
|
||||
local num = Menu.SelLine
|
||||
for i = Menu.SelLine + 1, 6, 1 do
|
||||
if Line[i].Type ~= nil and Line[i].Next ~= nil then
|
||||
Menu.SelLine=i
|
||||
break
|
||||
end
|
||||
end
|
||||
if num == Menu.SelLine then
|
||||
if Menu.Next ~= 0 then -- Next
|
||||
Menu.SelLine = 7
|
||||
elseif Menu.Prev ~= 0 then -- Prev
|
||||
Menu.SelLine = 8
|
||||
end
|
||||
end
|
||||
elseif Menu.Prev ~= 0 then -- Prev
|
||||
Menu.SelLine = 8
|
||||
end
|
||||
end
|
||||
else -- need to inc the value
|
||||
Value_Add(1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
if Menu.EditLine == nil then
|
||||
if Menu.SelLine ~= nil then
|
||||
if Menu.SelLine == 8 and Menu.Next ~= 0 then
|
||||
Menu.SelLine = 7
|
||||
elseif Menu.SelLine > 0 then
|
||||
if Menu.SelLine > 6 then
|
||||
Menu.SelLine = 7
|
||||
end
|
||||
local num = Menu.SelLine
|
||||
for i = Menu.SelLine-1, 0, -1 do
|
||||
if Line[i].Type ~= nil and Line[i].Next ~= nil then
|
||||
Menu.SelLine=i
|
||||
break
|
||||
end
|
||||
end
|
||||
if num == Menu.SelLine then -- Back
|
||||
Menu.SelLine = -1
|
||||
end
|
||||
else
|
||||
Menu.SelLine = -1 -- Back
|
||||
end
|
||||
end
|
||||
else -- need to dec the value
|
||||
Value_Add(-1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
if Menu.SelLine == -1 then -- Back
|
||||
Menu.Cur = Menu.Back
|
||||
Menu.Id = Menu.BackId
|
||||
Menu.SelLine = 0
|
||||
Phase = MENU_TITLE
|
||||
Waiting_RX = 0
|
||||
elseif Menu.SelLine == 7 then -- Next
|
||||
Menu.Cur = Menu.Next
|
||||
Menu.Id = Menu.NextId
|
||||
Menu.SelLine = 0
|
||||
Phase = MENU_TITLE
|
||||
Waiting_RX = 0
|
||||
elseif Menu.SelLine == 8 then -- Prev
|
||||
Menu.Cur = Menu.Prev
|
||||
Menu.Id = Menu.PrevId
|
||||
Menu.SelLine = 0
|
||||
Phase = MENU_TITLE
|
||||
Waiting_RX = 0
|
||||
elseif Menu.SelLine ~= nil and Line[Menu.SelLine].Next ~= nil then
|
||||
if Line[Menu.SelLine].Type == MENU then -- Next menu exist
|
||||
Menu.Cur = Line[Menu.SelLine].Next
|
||||
Menu.Id = Line[Menu.SelLine].NextId
|
||||
Phase = MENU_TITLE
|
||||
Waiting_RX = 0
|
||||
else
|
||||
-- value entry
|
||||
if Menu.EditLine == Menu.SelLine then
|
||||
Menu.EditLine = nil
|
||||
Value_Changed = 0
|
||||
Phase = VALUE_CHANGED
|
||||
Waiting_RX = 0
|
||||
else
|
||||
Menu.EditLine = Menu.SelLine
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function DSM_Send_Receive()
|
||||
if Waiting_RX == 0 then
|
||||
Waiting_RX = 1
|
||||
-- Need to send a request
|
||||
if Phase == RX_VERSION then -- request RX version
|
||||
DSM_Send(0x11,0x06,0x00,0x14,0x00,0x00)
|
||||
elseif Phase == WAIT_CMD then -- keep connection open
|
||||
DSM_Send(0x00,0x04,0x00,0x00)
|
||||
elseif Phase == MENU_TITLE then -- request menu title
|
||||
if Menu.Cur == nil then
|
||||
DSM_Send(0x12,0x06,0x00,0x14,0x00,0x00) -- first menu only
|
||||
Menu.Cur = 0
|
||||
else
|
||||
DSM_Send(0x16,0x06,Menu.Id,Menu.Cur,0x00,Menu.SelLine)
|
||||
end
|
||||
elseif Phase == MENU_LINES then -- request menu lines
|
||||
if Menu.CurLine == nil then
|
||||
DSM_Send(0x13,0x04,Menu.Id,Menu.Cur) -- line 0
|
||||
elseif Menu.CurLine >= 0x80 then
|
||||
local last_byte={0x40,0x01,0x02,0x04,0x00,0x00} -- unknown...
|
||||
DSM_Send(0x20,0x06,Menu.CurLine-0x80,Menu.CurLine-0x80,0x00,last_byte[Menu.CurLine-0x80+1]) -- line X
|
||||
else
|
||||
DSM_Send(0x14,0x06,Menu.Id,Menu.Cur,0x00,Menu.CurLine) -- line X
|
||||
end
|
||||
elseif Phase == MENU_VALUES then -- request menu values
|
||||
DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,Menu.CurLine) -- line X
|
||||
elseif Phase == VALUE_CHANGING then -- send value
|
||||
local value=Line[Menu.SelLine].Val
|
||||
if value < 0 then
|
||||
value = 0x10000 + value
|
||||
end
|
||||
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
|
||||
Phase = VALUE_CHANGING_WAIT
|
||||
elseif Phase == VALUE_CHANGED then -- send value
|
||||
if Value_Changed == 0 then
|
||||
local value=Line[Menu.SelLine].Val
|
||||
if value < 0 then
|
||||
value = 0x10000 + value
|
||||
end
|
||||
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
|
||||
Value_Changed = Value_Changed + 1
|
||||
Waiting_RX = 0
|
||||
elseif Value_Changed == 1 then
|
||||
DSM_Send(0x19,0x06,Line[Menu.SelLine].ValId,Menu.SelLine) -- validate
|
||||
-- Value_Changed = Value_Changed + 1
|
||||
-- Waiting_RX = 0
|
||||
--elseif Value_Changed == 2 then
|
||||
-- DSM_Send(0x1B,0x06,0x10,Menu.SelLine) -- validate again?
|
||||
-- Value_Changed = Value_Changed + 1
|
||||
end
|
||||
elseif Phase == VALUE_CHANGING_WAIT then
|
||||
DSM_Send(0x1A,0x06,Line[Menu.SelLine].ValId,Menu.SelLine)
|
||||
end
|
||||
multiBuffer(10,0x00);
|
||||
Retry = 50
|
||||
elseif multiBuffer(10) == 0x09 then
|
||||
-- Answer received
|
||||
--if multiBuffer(11) == 0x00 then -- waiting for commands?
|
||||
if multiBuffer(11) == 0x01 then -- read version
|
||||
--ex: 0x09 0x01 0x00 0x15 0x02 0x22 0x01 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
RX.Name = Get_Text(multiBuffer(13))
|
||||
RX.Version = multiBuffer(14).."."..multiBuffer(15).."."..multiBuffer(16)
|
||||
Phase = MENU_TITLE
|
||||
elseif multiBuffer(11) == 0x02 then -- read menu title
|
||||
--ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00
|
||||
Menu.Cur = multiBuffer(12)
|
||||
Menu.Id = multiBuffer(13)
|
||||
Menu.Title = Get_Text(multiBuffer(14)+multiBuffer(15)*256)
|
||||
Menu.Prev = multiBuffer(16)
|
||||
Menu.PrevId = multiBuffer(17)
|
||||
Menu.Next = multiBuffer(18)
|
||||
Menu.NextId = multiBuffer(19)
|
||||
Menu.Back = multiBuffer(20)
|
||||
Menu.BackId = multiBuffer(21)
|
||||
for i = 0, 6 do -- clear menu
|
||||
Line[i] = { Menu = nil, Id = nil, Type = nil, Text="", Next = nil, NextId = nil, ValLine = nil, ValId = nil, Min, Max, Def, Val, Unit, Step }
|
||||
end
|
||||
Menu.CurLine = nil
|
||||
if Menu.Next ~= 0 then
|
||||
Menu.SelLine = 7 -- highlight Next
|
||||
else
|
||||
Menu.SelLine = -1 -- highlight Back
|
||||
end
|
||||
Blink = 0
|
||||
Phase = MENU_LINES
|
||||
elseif multiBuffer(11) == 0x03 then -- read menu lines
|
||||
--ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00
|
||||
-- Menu Id line Type Text_idx Next V_Id Val_Min Val_Max Val_Def
|
||||
--ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00
|
||||
Menu.CurLine = multiBuffer(14)
|
||||
local line = Line[Menu.CurLine]
|
||||
line.Menu = multiBuffer(12)
|
||||
line.Id = multiBuffer(13) -- not quite sure yet
|
||||
line.Type = multiBuffer(15) -- not quite sure yet: 1C is text menu only, 4C/6C is text followed by text list, C0 is text followed by percentage value
|
||||
line.Text = Get_Text(multiBuffer(16)+multiBuffer(17)*256)
|
||||
if multiBuffer(18) == Menu.Cur then
|
||||
line.Next = nil
|
||||
else
|
||||
line.Next = multiBuffer(18) -- not quite sure yet: 1C=text menu=>next menu, others=>line number of the value
|
||||
end
|
||||
if Menu.SelLine == -1 and line.Next ~= nil then -- Auto select first line of the menu
|
||||
Menu.SelLine = Menu.CurLine
|
||||
end
|
||||
line.NextId = multiBuffer(19) -- not quite sure yet
|
||||
line.ValLine = multiBuffer(18) -- not quite sure yet
|
||||
line.ValId = multiBuffer(19) -- not quite sure yet
|
||||
line.Min = conv_int16(multiBuffer(20)+multiBuffer(21)*256)
|
||||
line.Max = conv_int16(multiBuffer(22)+multiBuffer(23)*256)
|
||||
line.Def = conv_int16(multiBuffer(24)+multiBuffer(25)*256)
|
||||
if line.Type == MENU then
|
||||
-- nothing to do on menu entries
|
||||
elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_MENU2 then
|
||||
line.Val = nil --line.Def - line.Min -- use default value not sure if needed
|
||||
line.Def = line.Min -- pointer to the start of the list in Text
|
||||
line.Max = line.Max - line.Min -- max index
|
||||
line.Min = 0 -- min index
|
||||
else -- default to numerical value
|
||||
line.Val = nil --line.Def -- use default value not sure if needed
|
||||
end
|
||||
if line.Type ~= 0x1C then -- value to follow
|
||||
line.Text = line.Text..":"
|
||||
end
|
||||
Phase = MENU_LINES
|
||||
elseif multiBuffer(11) == 0x04 then -- read menu values
|
||||
--ex: 0x09 0x04 0x53 0x10 0x00 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
-- Menu MeId line VaId Value
|
||||
--ex: 0x09 0x04 0x61 0x10 0x02 0x10 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
Menu.CurLine = multiBuffer(14)
|
||||
Line[Menu.CurLine].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256)
|
||||
Phase = MENU_VALUES
|
||||
elseif multiBuffer(11) == 0x05 then -- unknown... need to get through the lines...
|
||||
Menu.CurLine = 0x80 + multiBuffer(12)
|
||||
Phase = MENU_LINES
|
||||
elseif multiBuffer(11) == 0x00 and Phase == VALUE_CHANGING then
|
||||
Phase = VALUE_CHANGING_WAIT
|
||||
end
|
||||
-- Data processed
|
||||
Waiting_RX = 0
|
||||
multiBuffer(10,0x00)
|
||||
Retry = 50
|
||||
else
|
||||
Retry = Retry - 1
|
||||
if Retry <= 0 then
|
||||
-- Retry the RX request
|
||||
Retry = 50
|
||||
Waiting_RX = 0
|
||||
if Phase ~= RX_VERSION and Phase ~= VALUE_CHANGING_WAIT then
|
||||
Phase = WAIT_CMD
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function DSM_Display()
|
||||
lcd.clear()
|
||||
if LCD_W == 480 then
|
||||
--Draw title
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, "DSM Forward Programming", MENU_TITLE_COLOR)
|
||||
--Draw RX Menu
|
||||
if Phase == RX_VERSION then
|
||||
lcd.drawText(10,50,"No compatible DSM RX...", BLINK)
|
||||
else
|
||||
if Menu.Title ~= nil then
|
||||
local attrib=0;
|
||||
lcd.drawText(80,32,Menu.Title,MIDSIZE)
|
||||
for i = 0, 6 do
|
||||
if i == Menu.SelLine then
|
||||
attrib = INVERS
|
||||
else
|
||||
attrib = 0
|
||||
end
|
||||
if Line[i] ~= nil and Line[i].Type ~= nil then
|
||||
if Line[i].Type ~= MENU then -- list/value
|
||||
if Line[i].Val ~= nil then
|
||||
local text=""
|
||||
if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU2 then
|
||||
text = Get_Text(Line[i].Val+Line[i].Def)
|
||||
elseif Line[i].Type == PERCENTAGE_VALUE then
|
||||
text = Line[i].Val.." %"
|
||||
else
|
||||
text = Line[i].Val
|
||||
end
|
||||
if Menu.EditLine == Menu.SelLine then -- blink edited entry
|
||||
Blink = Blink + 1
|
||||
if Blink > 25 then
|
||||
attrib = 0
|
||||
if Blink > 50 then
|
||||
Blink = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
lcd.drawText(240,32+20*(i+2), text, attrib) -- display value
|
||||
end
|
||||
attrib = 0
|
||||
end
|
||||
lcd.drawText(10,32+20*(i+2), Line[i].Text, attrib) -- display text
|
||||
end
|
||||
end
|
||||
if Menu.SelLine == -1 then
|
||||
lcd.drawText(437,32, "Back", INVERS)
|
||||
else
|
||||
lcd.drawText(437,32, "Back", 0)
|
||||
end
|
||||
lcd.drawRectangle(437-5, 32-2, 47, 25)
|
||||
if Menu.Next ~= 0 then
|
||||
if Menu.SelLine == 7 then
|
||||
lcd.drawText(437,220, "Next",INVERS)
|
||||
else
|
||||
lcd.drawText(437,220, "Next")
|
||||
end
|
||||
lcd.drawRectangle(437-5, 220-2, 47, 25)
|
||||
end
|
||||
if Menu.Prev ~= 0 then
|
||||
if Menu.SelLine == 8 then
|
||||
lcd.drawText(5,220, "Prev",INVERS)
|
||||
else
|
||||
lcd.drawText(5,220, "Prev")
|
||||
end
|
||||
lcd.drawRectangle(5-5, 220-2, 47, 25)
|
||||
end
|
||||
end
|
||||
lcd.drawText(170,252, "RX "..RX.Name.." v"..RX.Version) -- display RX info
|
||||
end
|
||||
else
|
||||
-- --Draw RX Menu on LCD_W=128
|
||||
-- if multiBuffer( 4 ) == 0xFF then
|
||||
-- lcd.drawText(2,17,"No compatible DSM RX...",SMLSIZE)
|
||||
-- else
|
||||
-- if Retry_128 ~= 0 then
|
||||
-- --Intro page
|
||||
-- Retry_128 = Retry_128 - 1
|
||||
-- lcd.drawScreenTitle("DSM Forward Programming",0,0)
|
||||
-- lcd.drawText(2,17,"Press Prev Page for previous Menu" ,SMLSIZE)
|
||||
-- else
|
||||
-- --Menu page
|
||||
-- for line = 0, 7, 1 do
|
||||
-- for i = 0, 21-1, 1 do
|
||||
-- value=multiBuffer( line*21+6+i )
|
||||
-- if value > 0x80 then
|
||||
-- value = value - 0x80
|
||||
-- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
|
||||
-- else
|
||||
-- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function DSM_Init()
|
||||
--Set protocol to talk to
|
||||
multiBuffer( 0, string.byte('D') )
|
||||
--test if value has been written
|
||||
if multiBuffer( 0 ) ~= string.byte('D') then
|
||||
error("Not enough memory!")
|
||||
return 2
|
||||
end
|
||||
--Init TX buffer
|
||||
multiBuffer( 3, 0x00 )
|
||||
--Init RX buffer
|
||||
multiBuffer( 10, 0x00 )
|
||||
--Init telemetry
|
||||
multiBuffer( 0, string.byte('D') )
|
||||
multiBuffer( 1, string.byte('S') )
|
||||
multiBuffer( 2, string.byte('M') )
|
||||
|
||||
--Text to be displayed -> need to use a file instead?
|
||||
--RX names--
|
||||
Text[0x0014]="SPM4651T"
|
||||
Text[0x0015]="AR637T"
|
||||
--Lists--
|
||||
Text[0x0036]="Throttle"
|
||||
Text[0x0037]="Aileron"
|
||||
Text[0x0038]="Elevator"
|
||||
Text[0x0039]="Rudder"
|
||||
Text[0x003A]="Gear"
|
||||
for i=1,7 do -- 3B..41
|
||||
Text[0x003A+i]="Aux"..i
|
||||
end
|
||||
for i=1,8 do -- 41..49
|
||||
Text[0x0041+i]="XPlus-"..i
|
||||
end
|
||||
Text[0x004A]="Failsafe"
|
||||
Text[0x004B]="Main Menu"
|
||||
Text[0x004E]="Position"
|
||||
Text[0x0050]="Outputs"
|
||||
--Text[0x005E]="Inhibit"
|
||||
Text[0x005F]="Hold Last"
|
||||
Text[0x0060]="Preset"
|
||||
--Text[0x0061]="Custom"
|
||||
--Messages--
|
||||
Text[0x0090]="Apply"
|
||||
Text[0x0093]="Complete"
|
||||
Text[0x0094]="Done"
|
||||
Text[0x0097]="Factory Reset"
|
||||
Text[0x009A]="Capture Failsafe Positions"
|
||||
Text[0x009C]="Custom Failsafe"
|
||||
Text[0x00A5]="First Time Setup"
|
||||
Text[0x00F9]="Gyro settings"
|
||||
Text[0x0100]="Make sure the model has been"
|
||||
Text[0x0101]="configured, including wing type,"
|
||||
Text[0x0102]="reversing, travel, trimmed, etc."
|
||||
Text[0x0103]="before continuing setup."
|
||||
Text[0x0104]=""
|
||||
Text[0x0105]=""
|
||||
Text[0x0106]="Any wing type, channel assignment,"
|
||||
Text[0x0107]="subtrim, or servo reversing changes"
|
||||
Text[0x0108]="require running through initial"
|
||||
Text[0x0109]="setup again."
|
||||
Text[0x010A]=""
|
||||
Text[0x010B]=""
|
||||
|
||||
Text[0x019C]="Enter Receiver Bind Mode"
|
||||
Text[0x020A]="Restore from Backup"
|
||||
Text[0x0209]="Save to Backup"
|
||||
|
||||
Text[0x021A]="Set the model level,"
|
||||
Text[0x021B]="and press Continue."
|
||||
Text[0x021C]=""
|
||||
Text[0x021D]=""
|
||||
|
||||
Text[0x021F]="Set the model on its nose,"
|
||||
Text[0x0220]="and press Continue. If the"
|
||||
Text[0x0221]="orientation on the next"
|
||||
Text[0x0222]="screen is wrong go back"
|
||||
Text[0x0223]="and try again."
|
||||
Text[0x0224]="Continue"
|
||||
Text[0x0229]="Set Orientation Manually"
|
||||
|
||||
Text[0x0227]="Other settings"
|
||||
Text[0x022B]="WARNING!"
|
||||
Text[0x022C]="This will reset the"
|
||||
Text[0x022D]="configuration to factory"
|
||||
Text[0x022E]="defaults. This does not"
|
||||
Text[0x022F]="affect the backup config."
|
||||
Text[0x0230]=""
|
||||
Text[0x0231]="This will overwrite the"
|
||||
Text[0x0232]="backup memory with your"
|
||||
Text[0x0233]="current configuartion."
|
||||
Text[0x0234]=""
|
||||
Text[0x0235]=""
|
||||
Text[0x0236]="This will overwrite the"
|
||||
Text[0x0237]="current config with"
|
||||
Text[0x0238]="that which is in"
|
||||
Text[0x0239]="the backup memory."
|
||||
Text[0x023A]=""
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function DSM_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
DSM_Release()
|
||||
return 2
|
||||
else
|
||||
DSM_Menu(event)
|
||||
DSM_Send_Receive()
|
||||
DSM_Display()
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return { init=DSM_Init, run=DSM_Run }
|
||||
@@ -1,515 +0,0 @@
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local version = "v1.1"
|
||||
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
local FLPOI = 2
|
||||
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1 --row
|
||||
local refreshState = 0
|
||||
local refreshIndex = 0
|
||||
local refreshIndex3 = 0
|
||||
local pageOffset = 0
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
local modifications = {}
|
||||
local thistime = getTime()
|
||||
local lastTime = thistime
|
||||
local margin = 1
|
||||
local spacing = 8
|
||||
local configFields = {}
|
||||
local counter = 0
|
||||
local appId = 0
|
||||
|
||||
local function drawScreenTitle(title,page, pages)
|
||||
if math.fmod(math.floor(getTime()/100),10) == 0 then
|
||||
title = version
|
||||
end
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_COLOR)
|
||||
lcd.drawText(LCD_W-40, 5, page.."/"..pages, MENU_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, page, pages)
|
||||
end
|
||||
end
|
||||
|
||||
local interfaceconfig = {
|
||||
{"Sensor group select", VALUE, appId, nil, 0, 15},
|
||||
}
|
||||
|
||||
local settingsFields = {
|
||||
{"Software version", FLPOT, 0x0c, nil, 1, 100 },
|
||||
{"Physical ID", VALUE, 0x01, nil, 0, 26 },
|
||||
{"Application IDgroup", VALUE, 0x0D, nil, 0, 15 },
|
||||
{"Data rate(*100ms)", VALUE, 0x22, nil, 1, 255 },
|
||||
}
|
||||
|
||||
local telemetryFields = {
|
||||
{"TEMP1(C/F)", VALUE, 0x90, nil, -30, 600},
|
||||
{"TEMP2(C/F)", VALUE, 0x91, nil, -30, 600},
|
||||
{"SPEED(r/min)", VALUE, 0x92, nil, 0, 100000},
|
||||
{"Residual Volume(mL)", VALUE, 0x93, nil, 0, 60000},
|
||||
{"Residual Percent(%)", VALUE, 0x94, nil, 0, 100},
|
||||
{"FLOW(mL/min)", VALUE, 0x95, nil, 0, 2000},
|
||||
{"Max Flow(mL/min)", VALUE, 0x96, nil, 0, 2000},
|
||||
{"Avg Flow(mL/min)", VALUE, 0x97, nil, 0, 2000},
|
||||
}
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[2] == VALUE then
|
||||
min = field[5]
|
||||
max = field[6]
|
||||
elseif field[2] == COMBO then
|
||||
min = 0
|
||||
max = #(field[5]) - 1
|
||||
end
|
||||
if field[2] ~= FLPOT then --only read ?
|
||||
if field[2] == VALUE and field[6] > 256 then
|
||||
if field[4] > 1000 then
|
||||
step = step * 50
|
||||
field[4] = math.floor(field[4]/50)
|
||||
field[4] = field[4] *50
|
||||
elseif field[4] > 500 then
|
||||
step = step * 20
|
||||
field[4] = math.floor(field[4]/20)
|
||||
field[4] = field[4] *20
|
||||
elseif field[4] > 200 then
|
||||
step = step * 10
|
||||
field[4] = math.floor(field[4]/10)
|
||||
field[4] = field[4] *10
|
||||
else
|
||||
step = step * 1
|
||||
field[4] = math.floor(field[4]/1)
|
||||
field[4] = field[4] *1
|
||||
end
|
||||
end
|
||||
if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
|
||||
field[4] = field[4] + step
|
||||
end
|
||||
else
|
||||
field[4] = field[4]
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
page = 1 + ((page + step - 1 + #pages) % #pages)
|
||||
refreshIndex = 0
|
||||
pageOffset = 0
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
current = current + step
|
||||
if current > #fields then
|
||||
current = #fields
|
||||
elseif current < 1 then
|
||||
current = 1
|
||||
end
|
||||
if current > 7 + pageOffset then
|
||||
pageOffset = current - 7
|
||||
elseif current <= pageOffset then
|
||||
pageOffset = current - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function drawProgressBar()
|
||||
if LCD_W == 480 then
|
||||
local width = (300 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(100, 10, 300, 6)
|
||||
lcd.drawFilledRectangle(102, 13, width, 2);
|
||||
else
|
||||
local width = (60 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(45, 1, 60, 6)
|
||||
lcd.drawFilledRectangle(47, 3, width, 2);
|
||||
end
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage()
|
||||
lcd.clear()
|
||||
drawScreenTitle("GasSuit", page, #pages)
|
||||
if refreshIndex < #fields then
|
||||
drawProgressBar()
|
||||
end
|
||||
for index = 1, 7, 1 do
|
||||
local field = fields[pageOffset+index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
local attr = current == (pageOffset+index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
lcd.drawText(1, margin+ spacing * index, field[1])
|
||||
if field[4] == nil then
|
||||
lcd.drawText(LCD_W, margin+ spacing * index, "---", attr + RIGHT)
|
||||
else
|
||||
if field[2] == VALUE then
|
||||
if (field[3] == 0x90 or field[3] == 0x91) and field[4] == 500 then
|
||||
lcd.drawText(LCD_W, margin+ spacing * index, "---", attr + RIGHT)
|
||||
else
|
||||
|
||||
lcd.drawNumber(LCD_W, margin+ spacing * index, field[4] , attr + RIGHT)
|
||||
end
|
||||
elseif field[2] == COMBO then
|
||||
if field[4] >= 0 and field[4] < #(field[5]) then
|
||||
lcd.drawText(LCD_W, margin+ spacing * index, field[5][1+field[4]], attr + RIGHT)
|
||||
end
|
||||
elseif field[2] == FLPOT then
|
||||
lcd.drawText(LCD_W, margin+ spacing * index, field[4], attr + RIGHT)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function telemetryRead(fieldx)
|
||||
return sportTelemetryPush(0x1b, 0x30, appId, fieldx)
|
||||
end
|
||||
|
||||
local function telemetryListen(fieldx)
|
||||
return sportTelemetryPush(0x1b, 0, 0, 0)
|
||||
end
|
||||
|
||||
local function telemetryWrite(fieldx, valuex)
|
||||
return sportTelemetryPush(0x1b, 0x31, appId, fieldx + valuex*256)
|
||||
end
|
||||
|
||||
local telemetryPopTimeout = 0
|
||||
local function refreshNext()
|
||||
if refreshState == 0 and page ~= 3 then --
|
||||
if #modifications > 0 then --
|
||||
if modifications[1][1] ~= 0x0c then
|
||||
if modifications[1][1] == 0x22 then
|
||||
modifications[1][2] = modifications[1][2] + 0xf00
|
||||
end
|
||||
local modificationstmp = modifications[1][2]
|
||||
if modifications[1][1] == 0x8a or modifications[1][1] == 0x8b then
|
||||
if configFields[11][4]== 1 then
|
||||
modificationstmp = (modifications[1][2] - 32)*10
|
||||
modificationstmp = math.floor(modificationstmp/18)
|
||||
end
|
||||
end
|
||||
telemetryWrite(modifications[1][1], modificationstmp)
|
||||
refreshIndex = 0
|
||||
end
|
||||
modifications[1] = nil
|
||||
elseif refreshIndex < #fields then
|
||||
local field = fields[refreshIndex + 1]
|
||||
if telemetryRead(field[3]) == true then
|
||||
refreshState = 1
|
||||
telemetryPopTimeout = getTime() + 80
|
||||
end
|
||||
end
|
||||
elseif refreshState == 0 and page == 3 then
|
||||
if #modifications > 0 then
|
||||
if modifications[1][1] == 0x96 or modifications[1][1] == 0x97 or modifications[1][1] == 0x93 then
|
||||
telemetryWrite(modifications[1][1], 0)
|
||||
end
|
||||
modifications[1] = nil
|
||||
elseif refreshIndex < #fields then
|
||||
local field = fields[refreshIndex + 1]
|
||||
if telemetryRead(field[3]) == true then
|
||||
refreshState = 1
|
||||
telemetryPopTimeout = getTime() + 20
|
||||
end
|
||||
elseif refreshIndex >= #fields then
|
||||
refreshIndex = 0
|
||||
refreshState = 0
|
||||
end
|
||||
elseif refreshState == 1 and page ~= 3 then
|
||||
local physicalId, primId, dataId, value = sportTelemetryPop()
|
||||
if primId == 0x32 and dataId >= 0x0d00 and dataId <= 0x0d7f then
|
||||
local fieldId = value % 256
|
||||
local field = fields[refreshIndex + 1]
|
||||
if fieldId == field[3] then
|
||||
local value = math.floor(value / 256)
|
||||
if field[2] == COMBO then
|
||||
for index = 1, #(field[6]), 1 do
|
||||
if value == field[6][index] then
|
||||
value = index - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif field[2] == VALUE then
|
||||
value = value -- - field[8] + field[5]
|
||||
end
|
||||
if field[1] == "Software version" then
|
||||
local flo_string = string.char(value/16%16 + 48).."."..string.char(value%16 + 48)
|
||||
fields[refreshIndex + 1][4] = flo_string
|
||||
else
|
||||
fields[refreshIndex + 1][4] = value
|
||||
end
|
||||
refreshIndex = refreshIndex + 1
|
||||
refreshState = 0
|
||||
end
|
||||
elseif getTime() > telemetryPopTimeout then
|
||||
refreshState = 0
|
||||
end
|
||||
elseif refreshState == 1 and page == 3 then
|
||||
local pageID3 = 0
|
||||
local physicalId3, primId3, dataId3, value3 = sportTelemetryPop()
|
||||
if value3 ~= nil then
|
||||
pageID3 = value3 % 256
|
||||
value3 = math.floor(value3 / 0x100)
|
||||
end
|
||||
if primId3 == 0x32 and value3 ~= nil then
|
||||
if pageID3 == fields[refreshIndex + 1][3] then
|
||||
local field = fields[refreshIndex + 1]
|
||||
if field[2] == COMBO and #field == 6 then
|
||||
for index = 1, #(field[6]), 1 do
|
||||
if value3 == field[6][index] then
|
||||
value3 = index - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif field[2] == VALUE then
|
||||
if field[3] == 0x90 or field[3] == 0x91 then
|
||||
value3 = math.floor(value3 % 0x10000)
|
||||
if value3 > 0xf000 then
|
||||
value3 = value3 - 0x10000
|
||||
end
|
||||
if configFields[11][4]== 1 and (field[3] == 0x90 or field[3] == 0x91) then
|
||||
value3 =(value3*18)
|
||||
value3 = math.floor(value3/10)+32
|
||||
end
|
||||
else
|
||||
value3 = value3
|
||||
end
|
||||
end
|
||||
fields[refreshIndex + 1][4] = value3
|
||||
refreshIndex = refreshIndex + 1
|
||||
refreshState = 0
|
||||
end
|
||||
elseif getTime() > telemetryPopTimeout then
|
||||
refreshState = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[4]
|
||||
if field[2] == COMBO and #field == 6 then
|
||||
value = field[6][1+value]
|
||||
elseif field[2] == VALUE and #field == 6 then
|
||||
value = value -- + field[8] - field[5]
|
||||
elseif field[2] == FLPOT then
|
||||
value = 0
|
||||
end
|
||||
modifications[#modifications+1] = {field[3], value}
|
||||
end
|
||||
|
||||
-- Main1
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
if fields[current][4] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage()
|
||||
return 0
|
||||
end
|
||||
|
||||
local function runConfigPage(event)
|
||||
fields = configFields
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local function runSettingsPage(event)
|
||||
fields = settingsFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
local function runTelemetryPage(event)
|
||||
fields = telemetryFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit, refreshState, refreshIndex = 1, false, 0, 0
|
||||
if LCD_W == 480 then
|
||||
margin = 10
|
||||
spacing = 20
|
||||
end
|
||||
if LCD_W == 128 then
|
||||
configFields = {
|
||||
{"CDI off speed limit", VALUE, 0x81, nil, 10,10000}, -- 1
|
||||
{"Milliliter per pulse", VALUE, 0x80, nil, 1, 2000}, -- 2
|
||||
{"Volume", VALUE, 0x83, nil, 10,60000}, -- 3
|
||||
-- {"Flow trigger", VALUE, 0x84, nil, 5, 50 },
|
||||
-- {"Flow Reset", COMBO, 0x85, nil, { "ON", "OFF" }, {1 , 0}},
|
||||
{"Auto Reset", COMBO, 0x8d, nil, { "ON", "OFF" }, {0 , 1}}, -- 4
|
||||
{"Reset settings", COMBO, 0x86, nil,{ "YES", "NO" }, {1 , 0} }, -- 5
|
||||
{"Volume alarm(%)", VALUE, 0x87, nil, 0, 90 }, -- 6
|
||||
{"Max.Flow alarm", VALUE, 0x88, nil, 0, 2000 }, -- 7
|
||||
{"Over speed alarm", VALUE, 0x89, nil, 0, 10000 }, -- 8
|
||||
{"Over temp1 alarm", VALUE, 0x8a, nil, 0, 600 }, -- 9
|
||||
{"Over temp2 alarm", VALUE, 0x8b, nil, 0, 600 }, -- 10
|
||||
{"Temperature C/F", COMBO, 0x8c, nil,{ "C", "F" }, {0 , 1} }, -- 11
|
||||
}
|
||||
else
|
||||
configFields = {
|
||||
{"CDI off speed limit(*100RPM)", VALUE, 0x81, nil, 10,10000},
|
||||
{"Milliliter per pulse(*0.001mL/pul)", VALUE, 0x80, nil, 1, 2000},
|
||||
{"Volume(mL)", VALUE, 0x83, nil, 10,60000},
|
||||
-- {"Flow trigger(mL/min)", VALUE, 0x84, nil, 5, 50 },
|
||||
-- {"Flow Reset", COMBO, 0x85, nil, { "ON", "OFF" }, {1 , 0}},
|
||||
{"Auto Reset", COMBO, 0x8d, nil, { "ON", "OFF" }, {0 , 1}},
|
||||
{"Reset to factory settings", COMBO, 0x86, nil,{ "YES", "NO" }, {1 , 0} },
|
||||
{"Volume alarm(%)", VALUE, 0x87, nil, 0, 90 },
|
||||
{"Max.Flow alarm(mL/min)", VALUE, 0x88, nil, 0, 2000 },
|
||||
{"Over speed alarm(*100RPM)", VALUE, 0x89, nil, 0, 10000 },
|
||||
{"Over temperature1 alarm(C/F)", VALUE, 0x8a, nil, 0, 600 },
|
||||
{"Over temperature2 alarm(C/F)", VALUE, 0x8b, nil, 0, 600 },
|
||||
{"Temperature Celsius/Fahrenheit", COMBO, 0x8c, nil,{ "C", "F" }, {0 , 1} },
|
||||
}
|
||||
end
|
||||
|
||||
pages = {
|
||||
runConfigPage,
|
||||
runSettingsPage,
|
||||
runTelemetryPage,
|
||||
}
|
||||
|
||||
-- Warning : GaSuite tool requires Temp2 to be connected and discovered for script to work
|
||||
for index = 1, 40, 1 do
|
||||
local sensor = model.getSensor(index)
|
||||
if sensor ~= nil and sensor.id >= 0x0d10 and sensor.id <= 0x0d1f then
|
||||
appId = sensor.id
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if appId == 0 then
|
||||
error("No GasSuit sensor in this model!")
|
||||
end
|
||||
end
|
||||
|
||||
local function background()
|
||||
local tonefrq,tonelength,tonepause
|
||||
thistime = getTime()
|
||||
lastTime = thistime
|
||||
refreshNext()
|
||||
if page == 3 then --alarm
|
||||
local alarmnum = 0
|
||||
if fields[3][4] ~= nil and configFields[9][4] ~= nil then
|
||||
local speedtest = fields[3][4]
|
||||
local speedover = configFields[9][4]*100
|
||||
if speedtest >= speedover then
|
||||
tonefrq = 800 + math.max(0,math.floor((speedtest - speedover)/10))
|
||||
tonelength = 50 + math.max(0,(150 - math.floor((speedtest - speedover)/10)))
|
||||
tonepause = tonelength
|
||||
playTone(tonefrq, tonelength, tonepause, PLAY_BACKGROUND,10)
|
||||
alarmnum = alarmnum + 1
|
||||
end
|
||||
end
|
||||
if fields[5][4] ~= nil and configFields[7][4] ~= nil then
|
||||
local Residualtest = fields[5][4]
|
||||
local Residualline = configFields[6][4]
|
||||
if Residualtest < Residualline then
|
||||
tonefrq = 400
|
||||
tonelength = 100
|
||||
tonepause = 1000 + math.floor( Residualline - Residualtest )*30
|
||||
playTone(tonefrq, tonelength, tonepause, PLAY_BACKGROUND,10)
|
||||
alarmnum = alarmnum + 1
|
||||
end
|
||||
end
|
||||
if fields[6][4] ~= nil and configFields[8][4] ~= nil then
|
||||
local Flowtest = fields[6][4]
|
||||
local Flowover = configFields[7][4]
|
||||
if Flowtest > Flowover then
|
||||
tonefrq = 400
|
||||
tonelength = 100
|
||||
tonepause = 200
|
||||
playTone(tonefrq, tonelength, tonepause, PLAY_BACKGROUND,10)
|
||||
alarmnum = alarmnum + 1
|
||||
end
|
||||
end
|
||||
if fields[1][4] ~= nil and configFields[10][4] ~= nil then
|
||||
local temp1test = fields[1][4] --
|
||||
local temp1over = configFields[9][4]
|
||||
if temp1test > temp1over and (temp1test ~= 500 and temp1test ~= 932) then
|
||||
tonefrq = 2000
|
||||
tonelength = 100
|
||||
tonepause = 900
|
||||
playTone(tonefrq, tonelength, tonepause, PLAY_BACKGROUND,10)
|
||||
alarmnum = alarmnum + 1
|
||||
end
|
||||
end
|
||||
if fields[2][4] ~= nil and configFields[11][4] ~= nil then
|
||||
local temp2test = fields[2][4]
|
||||
local temp2over = configFields[10][4]
|
||||
if temp2test > temp2over and (temp2test ~= 500 and temp2test ~= 932) then
|
||||
tonefrq = 2000
|
||||
tonelength = 300
|
||||
tonepause = 700
|
||||
playTone(tonefrq, tonelength, tonepause, PLAY_BACKGROUND,10)
|
||||
alarmnum = alarmnum + 1
|
||||
end
|
||||
end
|
||||
if alarmnum > 1 then
|
||||
playTone(2000, 100, 100, PLAY_BACKGROUND,10)
|
||||
end
|
||||
alarmnum = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a sensor script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
selectPage(1)
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
||||
killEvents(event);
|
||||
selectPage(-1)
|
||||
end
|
||||
local result = pages[page](event)
|
||||
if page ~= 3 then
|
||||
refreshNext()
|
||||
end
|
||||
background()
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, background=background, run=run }
|
||||
@@ -1,464 +0,0 @@
|
||||
--- - #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
----- # #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local version = "v1.01"
|
||||
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1
|
||||
local refreshState = 0
|
||||
local refreshIndex = 0
|
||||
local pageOffset = 0
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
local modifications = {}
|
||||
local margin = 1
|
||||
local spacing = 8
|
||||
local numberPerPage = 7
|
||||
|
||||
local configFields = {
|
||||
{ "Self_stable mode", COMBO, 0x80, nil, { "disable", "enable"} },
|
||||
{ "Sbus out", COMBO, 0x81, nil, { "disable", "enable"} },
|
||||
{ "VOut1(V)", VALUE, 0xB2, nil, 50, 84},
|
||||
{ "VOut2(V)", VALUE, 0xB3, nil, 50, 84},
|
||||
}
|
||||
|
||||
|
||||
local failsafeFields = {
|
||||
{ "CH1 failsafe", VALUE, 0x82, 150, 80, 220},
|
||||
{ "CH2 failsafe", VALUE, 0x82, 150, 80, 220},
|
||||
{ "CH3 failsafe", VALUE, 0x83, 150, 80, 220},
|
||||
{ "CH4 failsafe", VALUE, 0x83, 150, 80, 220},
|
||||
{ "CH5 failsafe", VALUE, 0x84, 150, 80, 220},
|
||||
{ "CH6 failsafe", VALUE, 0x84, 150, 80, 220},
|
||||
{ "CH7 failsafe", VALUE, 0x85, 150, 80, 220},
|
||||
{ "CH8 failsafe", VALUE, 0x85, 150, 80, 220},
|
||||
{ "CH9 failsafe", VALUE, 0x86, 150, 80, 220},
|
||||
{ "CH10 failsafe", VALUE, 0x86, 150, 80, 220},
|
||||
{ "CH11 failsafe", VALUE, 0x87, 150, 80, 220},
|
||||
{ "CH12 failsafe", VALUE, 0x87, 150, 80, 220},
|
||||
{ "CH13 failsafe", VALUE, 0x88, 150, 80, 220},
|
||||
{ "CH14 failsafe", VALUE, 0x88, 150, 80, 220},
|
||||
{ "CH15 failsafe", VALUE, 0x89, 150, 80, 220},
|
||||
{ "CH16 failsafe", VALUE, 0x89, 150, 80, 220},
|
||||
{ "CH17 failsafe", VALUE, 0x8A, 150, 80, 220},
|
||||
{ "CH18 failsafe", VALUE, 0x8A, 150, 80, 220},
|
||||
{ "CH19 failsafe", VALUE, 0x8B, 150, 80, 220},
|
||||
{ "CH20 failsafe", VALUE, 0x8B, 150, 80, 220},
|
||||
{ "CH21 failsafe", VALUE, 0x8C, 150, 80, 220},
|
||||
{ "CH22 failsafe", VALUE, 0x8C, 150, 80, 220},
|
||||
{ "CH23 failsafe", VALUE, 0x8D, 150, 80, 220},
|
||||
{ "CH24 failsafe", VALUE, 0x8D, 150, 80, 220},
|
||||
}
|
||||
|
||||
local rx1PinMapFields = {
|
||||
{ "CH1 RX1 map", VALUE, 0x8E, 1, 0, 16},
|
||||
{ "CH2 RX1 map", VALUE, 0x8E, 2, 0, 16},
|
||||
{ "CH3 RX1 map", VALUE, 0x8F, 3, 0, 16},
|
||||
{ "CH4 RX1 map", VALUE, 0x8F, 4, 0, 16},
|
||||
{ "CH5 RX1 map", VALUE, 0x90, 5, 0, 16},
|
||||
{ "CH6 RX1 map", VALUE, 0x90, 6, 0, 16},
|
||||
{ "CH7 RX1 map", VALUE, 0x91, 7, 0, 16},
|
||||
{ "CH8 RX1 map", VALUE, 0x91, 8, 0, 16},
|
||||
{ "CH9 RX1 map", VALUE, 0x92, 9, 0, 16},
|
||||
{ "CH10 RX1 map", VALUE, 0x92, 10, 0, 16},
|
||||
{ "CH11 RX1 map", VALUE, 0x93, 11, 0, 16},
|
||||
{ "CH12 RX1 map", VALUE, 0x93, 12, 0, 16},
|
||||
{ "CH13 RX1 map", VALUE, 0x94, 13, 0, 16},
|
||||
{ "CH14 RX1 map", VALUE, 0x94, 14, 0, 16},
|
||||
{ "CH15 RX1 map", VALUE, 0x95, 15, 0, 16},
|
||||
{ "CH16 RX1 map", VALUE, 0x95, 16, 0, 16},
|
||||
{ "CH17 RX1 map", VALUE, 0x96, 1, 0, 16},
|
||||
{ "CH18 RX1 map", VALUE, 0x96, 2, 0, 16},
|
||||
{ "CH19 RX1 map", VALUE, 0x97, 3, 0, 16},
|
||||
{ "CH20 RX1 map", VALUE, 0x97, 4, 0, 16},
|
||||
{ "CH21 RX1 map", VALUE, 0x98, 5, 0, 16},
|
||||
{ "CH22 RX1 map", VALUE, 0x98, 6, 0, 16},
|
||||
{ "CH23 RX1 map", VALUE, 0x99, 7, 0, 16},
|
||||
{ "CH24 RX1 map", VALUE, 0x99, 8, 0, 16},
|
||||
}
|
||||
|
||||
local rx2PinMapFields = {
|
||||
{ "CH1 RX2 map", VALUE, 0x9A, 1, 0, 16},
|
||||
{ "CH2 RX2 map", VALUE, 0x9A, 2, 0, 16},
|
||||
{ "CH3 RX2 map", VALUE, 0x9B, 3, 0, 16},
|
||||
{ "CH4 RX2 map", VALUE, 0x9B, 4, 0, 16},
|
||||
{ "CH5 RX2 map", VALUE, 0x9C, 5, 0, 16},
|
||||
{ "CH6 RX2 map", VALUE, 0x9C, 6, 0, 16},
|
||||
{ "CH7 RX2 map", VALUE, 0x9D, 7, 0, 16},
|
||||
{ "CH8 RX2 map", VALUE, 0x9D, 8, 0, 16},
|
||||
{ "CH9 RX2 map", VALUE, 0x9E, 9, 0, 16},
|
||||
{ "CH10 RX2 map", VALUE, 0x9E, 10, 0, 16},
|
||||
{ "CH11 RX2 map", VALUE, 0x9F, 11, 0, 16},
|
||||
{ "CH12 RX2 map", VALUE, 0x9F, 12, 0, 16},
|
||||
{ "CH13 RX2 map", VALUE, 0xA0, 13, 0, 16},
|
||||
{ "CH14 RX2 map", VALUE, 0xA0, 14, 0, 16},
|
||||
{ "CH15 RX2 map", VALUE, 0xA1, 15, 0, 16},
|
||||
{ "CH16 RX2 map", VALUE, 0xA0, 16, 0, 16},
|
||||
{ "CH17 RX2 map", VALUE, 0xA2, 1, 0, 16},
|
||||
{ "CH18 RX2 map", VALUE, 0xA2, 2, 0, 16},
|
||||
{ "CH19 RX2 map", VALUE, 0xA3, 3, 0, 16},
|
||||
{ "CH20 RX2 map", VALUE, 0xA3, 4, 0, 16},
|
||||
{ "CH21 RX2 map", VALUE, 0xA4, 5, 0, 16},
|
||||
{ "CH22 RX2 map", VALUE, 0xA4, 6, 0, 16},
|
||||
{ "CH23 RX2 map", VALUE, 0xA5, 7, 0, 16},
|
||||
{ "CH24 RX2 map", VALUE, 0xA5, 8, 0, 16},
|
||||
}
|
||||
|
||||
local rx3PinMapFields = {
|
||||
{ "CH1 RX3 map", VALUE, 0xA6, 1, 0, 16},
|
||||
{ "CH2 RX3 map", VALUE, 0xA6, 2, 0, 16},
|
||||
{ "CH3 RX3 map", VALUE, 0xA7, 3, 0, 16},
|
||||
{ "CH4 RX3 map", VALUE, 0xA7, 4, 0, 16},
|
||||
{ "CH5 RX3 map", VALUE, 0xA8, 5, 0, 16},
|
||||
{ "CH6 RX3 map", VALUE, 0xA8, 6, 0, 16},
|
||||
{ "CH7 RX3 map", VALUE, 0xA9, 7, 0, 16},
|
||||
{ "CH8 RX3 map", VALUE, 0xA9, 8, 0, 16},
|
||||
{ "CH9 RX3 map", VALUE, 0xAA, 9, 0, 16},
|
||||
{ "CH10 RX3 map", VALUE, 0xAA, 10, 0, 16},
|
||||
{ "CH11 RX3 map", VALUE, 0xAB, 11, 0, 16},
|
||||
{ "CH12 RX3 map", VALUE, 0xAB, 12, 0, 16},
|
||||
{ "CH13 RX3 map", VALUE, 0xAC, 13, 0, 16},
|
||||
{ "CH14 RX3 map", VALUE, 0xAC, 14, 0, 16},
|
||||
{ "CH15 RX3 map", VALUE, 0xAD, 15, 0, 16},
|
||||
{ "CH16 RX3 map", VALUE, 0xAD, 16, 0, 16},
|
||||
{ "CH17 RX3 map", VALUE, 0xAE, 1, 0, 16},
|
||||
{ "CH18 RX3 map", VALUE, 0xAE, 2, 0, 16},
|
||||
{ "CH19 RX3 map", VALUE, 0xAF, 3, 0, 16},
|
||||
{ "CH20 RX3 map", VALUE, 0xAF, 4, 0, 16},
|
||||
{ "CH21 RX3 map", VALUE, 0xB0, 5, 0, 16},
|
||||
{ "CH22 RX3 map", VALUE, 0xB0, 6, 0, 16},
|
||||
{ "CH23 RX3 map", VALUE, 0xB1, 7, 0, 16},
|
||||
{ "CH24 RX3 map", VALUE, 0xB1, 8, 0, 16},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
local function drawScreenTitle(title, page, pages)
|
||||
if math.fmod(math.floor(getTime() / 100), 10) == 0 then
|
||||
title = version
|
||||
end
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||
lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_TITLE_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, page, pages)
|
||||
end
|
||||
end
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[2] == VALUE then
|
||||
min = field[5]
|
||||
max = field[6]
|
||||
elseif field[2] == COMBO then
|
||||
min = 0
|
||||
max = #(field[5]) - 1
|
||||
end
|
||||
if page == 2 and step < 0 and field[4] == min then
|
||||
field[4] = 0
|
||||
elseif page == 2 and step > 0 and field[4] == 0 then
|
||||
field[4] = min
|
||||
else
|
||||
if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
|
||||
field[4] = field[4] + step
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
local pagesNum = #pages
|
||||
if configFields[1][4] == 1 then
|
||||
pagesNum = 1
|
||||
elseif configFields[2][4] == 1 then
|
||||
pagesNum = pagesNum - 1
|
||||
end
|
||||
page = 1 + ((page + step - 1 + pagesNum) % pagesNum)
|
||||
refreshIndex = 0
|
||||
pageOffset = 0
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
current = 1 + ((current + step - 1 + #fields) % #fields)
|
||||
if current > numberPerPage + pageOffset then
|
||||
pageOffset = current - numberPerPage
|
||||
elseif current <= pageOffset then
|
||||
pageOffset = current - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function drawProgressBar()
|
||||
if LCD_W == 480 then
|
||||
local width = (300 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(100, 10, 300, 6)
|
||||
lcd.drawFilledRectangle(102, 12, width, 2)
|
||||
else
|
||||
local width = (60 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(45, 1, 60, 6)
|
||||
lcd.drawFilledRectangle(47, 3, width, 2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldPage()
|
||||
lcd.clear()
|
||||
|
||||
local pagesNum = #pages
|
||||
if configFields[1][4] == 1 then
|
||||
pagesNum = 1
|
||||
elseif configFields[2][4] == 1 then
|
||||
pagesNum = pagesNum - 1
|
||||
end
|
||||
drawScreenTitle("RB30/RB40", page, pagesNum)
|
||||
|
||||
if refreshIndex < #fields then
|
||||
drawProgressBar()
|
||||
end
|
||||
|
||||
for index = 1, numberPerPage, 1 do
|
||||
local field = fields[pageOffset + index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
|
||||
lcd.drawText(1, margin + spacing * index, field[1], attr)
|
||||
|
||||
if field[4] == nil then
|
||||
lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr)
|
||||
else
|
||||
if field[2] == VALUE then
|
||||
if page == 2 then
|
||||
if field[4] == 0 then
|
||||
lcd.drawText(LCD_W, margin + spacing * index, "No pulse", RIGHT + attr)
|
||||
else
|
||||
lcd.drawNumber(LCD_W, margin + spacing * index, field[4] * 10, RIGHT + attr)
|
||||
end
|
||||
else
|
||||
if field[4] == 0 then
|
||||
lcd.drawText(LCD_W, margin + spacing * index, "No map", RIGHT + attr)
|
||||
else
|
||||
if field[3] == 0xB2 or field[3] == 0xB3 then
|
||||
lcd.drawNumber(LCD_W, margin + spacing * index, field[4] , attr + RIGHT + PREC1)
|
||||
else
|
||||
lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif field[2] == COMBO then
|
||||
if field[4] >= 0 and field[4] < #(field[5]) then
|
||||
lcd.drawText(LCD_W, margin + spacing * index, field[5][field[4] + 1], RIGHT + attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function telemetryIdle(field)
|
||||
return sportTelemetryPush(0x1C, 0x21, 0x0b80, field)
|
||||
end
|
||||
|
||||
local function telemetryUnIdle(field)
|
||||
return sportTelemetryPush(0x1C, 0x20, 0x0b80, field)
|
||||
end
|
||||
|
||||
local function telemetryRead(field)
|
||||
return sportTelemetryPush(0x1C, 0x30, 0x0b80, field)
|
||||
end
|
||||
|
||||
local function telemetryWrite(field, value)
|
||||
return sportTelemetryPush(0x1C, 0x31, 0x0b80, field + value * 256)
|
||||
end
|
||||
|
||||
local telemetryPopTimeout = 0
|
||||
local function refreshNext()
|
||||
if refreshState == 0 then
|
||||
if #modifications > 0 then
|
||||
telemetryWrite(modifications[1][1], modifications[1][2])
|
||||
modifications[1] = nil
|
||||
refreshIndex = 0
|
||||
refreshState = 0
|
||||
elseif refreshIndex < #fields then
|
||||
local field = fields[refreshIndex + 1]
|
||||
if page > 1 then
|
||||
field = fields[refreshIndex + 2]
|
||||
end
|
||||
if telemetryRead(field[3]) == true then
|
||||
refreshState = 1
|
||||
telemetryPopTimeout = getTime() + 100 -- normal delay is 500ms
|
||||
end
|
||||
end
|
||||
elseif refreshState == 1 then
|
||||
local physicalId, primId, dataId, value = sportTelemetryPop()
|
||||
if primId == 0x32 and (dataId >= 0x0b80 or dataId <= 0x0b8f) then
|
||||
local fieldId = value % 256
|
||||
local field = fields[refreshIndex + 1]
|
||||
if fieldId == field[3] then
|
||||
value = math.floor(value / 256)
|
||||
if field[2] == COMBO then
|
||||
fields[refreshIndex + 1][4] = value
|
||||
else
|
||||
fields[refreshIndex + 1][4] = value % 256
|
||||
if page > 1 then
|
||||
value = math.floor(value / 256)
|
||||
fields[refreshIndex + 2][4] = value
|
||||
end
|
||||
end
|
||||
if page > 1 then
|
||||
refreshIndex = refreshIndex + 2
|
||||
else
|
||||
refreshIndex = refreshIndex + 1
|
||||
end
|
||||
refreshState = 0
|
||||
end
|
||||
elseif getTime() > telemetryPopTimeout then
|
||||
fields[refreshIndex + 1][4] = nil
|
||||
if page > 1 then
|
||||
fields[refreshIndex + 2][4] = nil
|
||||
refreshIndex = refreshIndex + 2
|
||||
else
|
||||
refreshIndex = refreshIndex + 1
|
||||
end
|
||||
refreshState = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[4]
|
||||
if field[2] == COMBO and #field == 6 then
|
||||
value = field[6][1 + value]
|
||||
elseif field[2] == VALUE and #field == 8 then
|
||||
value = value + field[8] - field[5]
|
||||
end
|
||||
|
||||
if page > 1 then
|
||||
if current % 2 == 1 then
|
||||
value = value + fields[current + 1][4] * 256
|
||||
elseif current % 2 == 0 then
|
||||
value = fields[current - 1][4] + value * 256
|
||||
end
|
||||
end
|
||||
modifications[#modifications + 1] = { field[3], value }
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
telemetryUnIdle(0x80)
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
if fields[current][4] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldPage()
|
||||
return 0
|
||||
end
|
||||
|
||||
local function runConfigPage(event)
|
||||
fields = configFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
local function runFailsafePage(event)
|
||||
fields = failsafeFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
local function runRx1PinMapPage(event)
|
||||
fields = rx1PinMapFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
local function runRx2PinMapPage(event)
|
||||
fields = rx2PinMapFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
local function runRx3PinMapPage(event)
|
||||
fields = rx3PinMapFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit, refreshState, refreshIndex = 1, false, 0, 0
|
||||
if LCD_W == 480 then
|
||||
margin = 10
|
||||
spacing = 20
|
||||
numberPerPage = 12
|
||||
end
|
||||
pages = {
|
||||
runConfigPage,
|
||||
runFailsafePage,
|
||||
runRx1PinMapPage,
|
||||
runRx2PinMapPage,
|
||||
runRx3PinMapPage
|
||||
}
|
||||
telemetryIdle(0x80)
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
if edit == false then
|
||||
selectPage(1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
||||
if edit == false then
|
||||
killEvents(event)
|
||||
selectPage(-1)
|
||||
end
|
||||
end
|
||||
|
||||
local result = pages[page](event)
|
||||
refreshNext()
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return { init = init, run = run }
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local version = "v1.2"
|
||||
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1 --row
|
||||
local refreshState = 0
|
||||
local refreshIndex = 0
|
||||
local pageOffset = 0
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
local modifications = {}
|
||||
local margin = 1
|
||||
local spacing = 8
|
||||
local appId = 0
|
||||
|
||||
local function drawScreenTitle(title,page, pages)
|
||||
if math.fmod(math.floor(getTime()/100),10) == 0 then
|
||||
title = version
|
||||
end
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_COLOR)
|
||||
lcd.drawText(LCD_W-40, 5, page.."/"..pages, MENU_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, page, pages)
|
||||
end
|
||||
end
|
||||
|
||||
local settingsFields = {
|
||||
{"SBEC OUTPUT (V)", VALUE, 0x80, nil, 50, 84 },
|
||||
{"Physical ID", VALUE, 0x01, nil, 0, 26 },
|
||||
{"Application IDgroup", VALUE, 0x0D, nil, 0, 15 },
|
||||
{"Data rate(*100ms)", VALUE, 0x22, nil, 1, 255 },
|
||||
}
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[2] == VALUE then
|
||||
min = field[5]
|
||||
max = field[6]
|
||||
elseif field[2] == COMBO then
|
||||
min = 0
|
||||
max = #(field[5]) - 1
|
||||
end
|
||||
if field[2] ~= FLPOT then --only read ?
|
||||
if field[2] == VALUE and field[6] > 256 then
|
||||
if field[4] > 1000 then
|
||||
step = step * 50
|
||||
field[4] = math.floor(field[4]/50)
|
||||
field[4] = field[4] *50
|
||||
elseif field[4] > 500 then
|
||||
step = step * 20
|
||||
field[4] = math.floor(field[4]/20)
|
||||
field[4] = field[4] *20
|
||||
elseif field[4] > 200 then
|
||||
step = step * 10
|
||||
field[4] = math.floor(field[4]/10)
|
||||
field[4] = field[4] *10
|
||||
else
|
||||
step = step * 1
|
||||
field[4] = math.floor(field[4]/1)
|
||||
field[4] = field[4] *1
|
||||
end
|
||||
end
|
||||
if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
|
||||
field[4] = field[4] + step
|
||||
end
|
||||
else
|
||||
field[4] = field[4]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
current = current + step
|
||||
if current > #fields then
|
||||
current = #fields
|
||||
elseif current < 1 then
|
||||
current = 1
|
||||
end
|
||||
if current > 7 + pageOffset then
|
||||
pageOffset = current - 7
|
||||
elseif current <= pageOffset then
|
||||
pageOffset = current - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function drawProgressBar()
|
||||
if LCD_W == 480 then
|
||||
local width = (300 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(100, 10, 300, 6)
|
||||
lcd.drawFilledRectangle(102, 13, width, 2);
|
||||
else
|
||||
local width = (60 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(45, 1, 60, 6)
|
||||
lcd.drawFilledRectangle(47, 3, width, 2);
|
||||
end
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage()
|
||||
lcd.clear()
|
||||
drawScreenTitle("SBEC", page, #pages)
|
||||
if refreshIndex < #fields then
|
||||
drawProgressBar()
|
||||
end
|
||||
for index = 1, 7, 1 do
|
||||
local field = fields[pageOffset+index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
local attr = current == (pageOffset+index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
lcd.drawText(1, margin+ spacing * index, field[1])
|
||||
if field[4] == nil then
|
||||
lcd.drawText(LCD_W, margin+ spacing * index, "---", attr + RIGHT)
|
||||
else
|
||||
if field[2] == VALUE then
|
||||
if field[3] == 0x80 then
|
||||
lcd.drawNumber(LCD_W, margin+ spacing * index, field[4] , attr + RIGHT + PREC1)
|
||||
else
|
||||
lcd.drawNumber(LCD_W, margin+ spacing * index, field[4] , attr + RIGHT)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function telemetryRead(fieldx)
|
||||
return sportTelemetryPush(0x17, 0x30, appId, fieldx)
|
||||
end
|
||||
|
||||
local function telemetryIdle(field)
|
||||
return sportTelemetryPush(0x17, 0x21, appId, field)
|
||||
end
|
||||
|
||||
local function telemetryUnIdle(field)
|
||||
return sportTelemetryPush(0x17, 0x20, appId, field)
|
||||
end
|
||||
|
||||
local function telemetryWrite(fieldx, valuex)
|
||||
return sportTelemetryPush(0x17, 0x31, appId, fieldx + valuex*256)
|
||||
end
|
||||
|
||||
local telemetryPopTimeout = 0
|
||||
local function refreshNext()
|
||||
if refreshState == 0 then
|
||||
if #modifications > 0 then
|
||||
local modificationstmp = modifications[1][2]
|
||||
telemetryWrite(modifications[1][1], modificationstmp)
|
||||
refreshIndex = 0
|
||||
modifications[1] = nil
|
||||
elseif refreshIndex < #fields then
|
||||
local field = fields[refreshIndex + 1]
|
||||
if telemetryRead(field[3]) == true then
|
||||
refreshState = 1
|
||||
telemetryPopTimeout = getTime() + 80
|
||||
end
|
||||
end
|
||||
elseif refreshState == 1 then
|
||||
local physicalId, primId, dataId, value = sportTelemetryPop()
|
||||
if primId == 0x32 and dataId == appId then
|
||||
local fieldId = value % 256
|
||||
local field = fields[refreshIndex + 1]
|
||||
if fieldId == field[3] then
|
||||
local value = math.floor(value / 256)
|
||||
if field[2] == VALUE then
|
||||
value = value
|
||||
end
|
||||
|
||||
fields[refreshIndex + 1][4] = value
|
||||
refreshIndex = refreshIndex + 1
|
||||
refreshState = 0
|
||||
end
|
||||
elseif getTime() > telemetryPopTimeout then
|
||||
refreshState = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[4]
|
||||
if field[2] == VALUE and #field == 6 then
|
||||
value = value
|
||||
end
|
||||
modifications[#modifications+1] = {field[3], value}
|
||||
end
|
||||
|
||||
-- Main1
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
telemetryUnIdle(0x80)
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
if fields[current][4] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage()
|
||||
return 0
|
||||
end
|
||||
|
||||
local function runSettingsPage(event)
|
||||
fields = settingsFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit, refreshState, refreshIndex = 1, false, 0, 0
|
||||
if LCD_W == 480 then
|
||||
margin = 10
|
||||
spacing = 20
|
||||
end
|
||||
|
||||
pages = {
|
||||
runSettingsPage,
|
||||
}
|
||||
|
||||
for index = 1, 40, 1 do
|
||||
local sensor = model.getSensor(index)
|
||||
if sensor ~= nil and sensor.id >= 0x0e50 and sensor.id <= 0x0e5f then
|
||||
appId = sensor.id
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if appId == 0 then
|
||||
error("No SBEC sensor in this model!")
|
||||
end
|
||||
|
||||
telemetryIdle(0x80)
|
||||
end
|
||||
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot run as a model script!")
|
||||
return 2
|
||||
end
|
||||
local result = pages[page](event)
|
||||
|
||||
refreshNext()
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, background=background, run=run }
|
||||
@@ -1,363 +0,0 @@
|
||||
--- - #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
----- # #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local version = "v2.00"
|
||||
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
|
||||
local COLUMN_2 = 300
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1
|
||||
local refreshState = 0
|
||||
local refreshIndex = 0
|
||||
local calibrationState = 0
|
||||
local pageOffset = 0
|
||||
local calibrationStep = 0
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
local modifications = {}
|
||||
local wingBitmaps = {}
|
||||
local mountBitmaps = {}
|
||||
local margin = 1
|
||||
local spacing = 8
|
||||
local counter = 0
|
||||
|
||||
local configFields = {
|
||||
{ "Wing type", COMBO, 0x80, nil, { "Normal", "Delta", "VTail" } },
|
||||
{ "Mounting type", COMBO, 0x81, nil, { "Horz", "Horz rev.", "Vert", "Vert rev." } },
|
||||
}
|
||||
|
||||
local wingBitmapsFile = { "/SCRIPTS/TOOLS/bmp/plane.bmp", "/SCRIPTS/TOOLS/bmp/delta.bmp", "/SCRIPTS/TOOLS/bmp/vtail.bmp" }
|
||||
local mountBitmapsFile = { "/SCRIPTS/TOOLS/bmp/horz.bmp", "/SCRIPTS/TOOLS/bmp/horz-r.bmp", "/SCRIPTS/TOOLS/bmp/vert.bmp", "/SCRIPTS/TOOLS/bmp/vert-r.bmp" }
|
||||
|
||||
local settingsFields = {
|
||||
{"SxR functions", COMBO, 0x9C, nil, { "Disable", "Enable" } },
|
||||
{"Quick Mode:", COMBO, 0xAA, nil, { "Disable", "Enable" } },
|
||||
{"CH5 mode", COMBO, 0xA8, nil, { "AIL2", "AUX1" } },
|
||||
{"CH6 mode", COMBO, 0xA9, nil, { "ELE2", "AUX2" } },
|
||||
{"AIL direction", COMBO, 0x82, nil, { "Normal", "Invers" }, { 255, 0 } },
|
||||
{"ELE direction", COMBO, 0x83, nil, { "Normal", "Invers" }, { 255, 0 } },
|
||||
{"RUD direction", COMBO, 0x84, nil, { "Normal", "Invers" }, { 255, 0 } },
|
||||
{"AIL2 direction", COMBO, 0x9A, nil, { "Normal", "Invers" }, { 255, 0 } },
|
||||
{"ELE2 direction", COMBO, 0x9B, nil, { "Normal", "Invers" }, { 255, 0 } },
|
||||
{"AIL stab gain", VALUE, 0x85, nil, 0, 200, "%"},
|
||||
{"ELE stab gain", VALUE, 0x86, nil, 0, 200, "%"},
|
||||
{"RUD stab gain", VALUE, 0x87, nil, 0, 200, "%"},
|
||||
{"AIL autolvl gain", VALUE, 0x88, nil, 0, 200, "%"},
|
||||
{"ELE autolvl gain", VALUE, 0x89, nil, 0, 200, "%"},
|
||||
{"ELE hover gain", VALUE, 0x8C, nil, 0, 200, "%"},
|
||||
{"RUD hover gain", VALUE, 0x8D, nil, 0, 200, "%"},
|
||||
{"AIL knife gain", VALUE, 0x8E, nil, 0, 200, "%"},
|
||||
{"RUD knife gain", VALUE, 0x90, nil, 0, 200, "%"},
|
||||
{"AIL autolvl offset", VALUE, 0x91, nil, -20, 20, "%", 0x6C},
|
||||
{"ELE autolvl offset", VALUE, 0x92, nil, -20, 20, "%", 0x6C},
|
||||
{"ELE hover offset", VALUE, 0x95, nil, -20, 20, "%", 0x6C},
|
||||
{"RUD hover offset", VALUE, 0x96, nil, -20, 20, "%", 0x6C},
|
||||
{"AIL knife offset", VALUE, 0x97, nil, -20, 20, "%", 0x6C},
|
||||
{"RUD knife offset", VALUE, 0x99, nil, -20, 20, "%", 0x6C},
|
||||
}
|
||||
|
||||
local calibrationFields = {
|
||||
{ "X:", VALUE, 0x9E, 0, -100, 100, "%" },
|
||||
{ "Y:", VALUE, 0x9F, 0, -100, 100, "%" },
|
||||
{ "Z:", VALUE, 0xA0, 0, -100, 100, "%" }
|
||||
}
|
||||
|
||||
local function drawScreenTitle(title, page, pages)
|
||||
if math.fmod(math.floor(getTime() / 100), 10) == 0 then
|
||||
title = version
|
||||
end
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_COLOR)
|
||||
lcd.drawText(LCD_W - 40, 5, page .. "/" .. pages, MENU_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, page, pages)
|
||||
end
|
||||
end
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[2] == VALUE then
|
||||
min = field[5]
|
||||
max = field[6]
|
||||
elseif field[2] == COMBO then
|
||||
min = 0
|
||||
max = #(field[5]) - 1
|
||||
end
|
||||
if (step < 0 and field[4] > min) or (step > 0 and field[4] < max) then
|
||||
field[4] = field[4] + step
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
page = 1 + ((page + step - 1 + #pages) % #pages)
|
||||
refreshIndex = 0
|
||||
calibrationStep = 0
|
||||
pageOffset = 0
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
current = 1 + ((current + step - 1 + #fields) % #fields)
|
||||
if current > 7 + pageOffset then
|
||||
pageOffset = current - 7
|
||||
elseif current <= pageOffset then
|
||||
pageOffset = current - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function drawProgressBar()
|
||||
if LCD_W == 480 then
|
||||
local width = (300 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(100, 10, 300, 6)
|
||||
lcd.drawFilledRectangle(102, 13, width, 2);
|
||||
else
|
||||
local width = (60 * refreshIndex) / #fields
|
||||
lcd.drawRectangle(45, 1, 60, 6)
|
||||
lcd.drawFilledRectangle(47, 3, width, 2);
|
||||
end
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage(event)
|
||||
lcd.clear()
|
||||
drawScreenTitle("SxR", page, #pages)
|
||||
|
||||
if refreshIndex < #fields then
|
||||
drawProgressBar()
|
||||
end
|
||||
|
||||
for index = 1, 10, 1 do
|
||||
local field = fields[pageOffset + index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local attr = current == (pageOffset + index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
|
||||
lcd.drawText(1, margin + spacing * index, field[1], attr)
|
||||
|
||||
if field[4] == nil then
|
||||
lcd.drawText(LCD_W, margin + spacing * index, "---", RIGHT + attr)
|
||||
else
|
||||
if field[2] == VALUE then
|
||||
lcd.drawNumber(LCD_W, margin + spacing * index, field[4], RIGHT + attr)
|
||||
elseif field[2] == COMBO then
|
||||
if field[4] >= 0 and field[4] < #(field[5]) then
|
||||
lcd.drawText(LCD_W, margin + spacing * index, field[5][1 + field[4]], RIGHT + attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function telemetryRead(field)
|
||||
return sportTelemetryPush(0x17, 0x30, 0x0C30, field)
|
||||
end
|
||||
|
||||
local function telemetryWrite(field, value)
|
||||
return sportTelemetryPush(0x17, 0x31, 0x0C30, field + value * 256)
|
||||
end
|
||||
|
||||
local telemetryPopTimeout = 0
|
||||
local function refreshNext()
|
||||
if refreshState == 0 then
|
||||
if calibrationState == 1 then
|
||||
if telemetryWrite(0x9D, calibrationStep) == true then
|
||||
refreshState = 1
|
||||
calibrationState = 2
|
||||
telemetryPopTimeout = getTime() + 120 -- normal delay is 500ms
|
||||
end
|
||||
elseif #modifications > 0 then
|
||||
telemetryWrite(modifications[1][1], modifications[1][2])
|
||||
modifications[1] = nil
|
||||
elseif refreshIndex < #fields then
|
||||
local field = fields[refreshIndex + 1]
|
||||
if telemetryRead(field[3]) == true then
|
||||
refreshState = 1
|
||||
telemetryPopTimeout = getTime() + 80 -- normal delay is 500ms
|
||||
end
|
||||
end
|
||||
elseif refreshState == 1 then
|
||||
local physicalId, primId, dataId, value = sportTelemetryPop()
|
||||
if physicalId == 0x1A and primId == 0x32 and dataId == 0x0C30 then
|
||||
local fieldId = value % 256
|
||||
if calibrationState == 2 then
|
||||
if fieldId == 0x9D then
|
||||
refreshState = 0
|
||||
calibrationState = 0
|
||||
calibrationStep = (calibrationStep + 1) % 7
|
||||
end
|
||||
else
|
||||
local field = fields[refreshIndex + 1]
|
||||
if fieldId == field[3] then
|
||||
local value = math.floor(value / 256)
|
||||
if field[3] == 0xAA then
|
||||
value = bit32.band(value, 0x0001)
|
||||
end
|
||||
if field[3] >= 0x9E and field[3] <= 0xA0 then
|
||||
local b1 = value % 256
|
||||
local b2 = math.floor(value / 256)
|
||||
value = b1 * 256 + b2
|
||||
value = value - bit32.band(value, 0x8000) * 2
|
||||
end
|
||||
if field[2] == COMBO and #field == 6 then
|
||||
for index = 1, #(field[6]), 1 do
|
||||
if value == field[6][index] then
|
||||
value = index - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif field[2] == VALUE and #field == 8 then
|
||||
value = value - field[8] + field[5]
|
||||
end
|
||||
fields[refreshIndex + 1][4] = value
|
||||
refreshIndex = refreshIndex + 1
|
||||
refreshState = 0
|
||||
end
|
||||
end
|
||||
elseif getTime() > telemetryPopTimeout then
|
||||
fields[refreshIndex + 1][4] = nil
|
||||
refreshIndex = refreshIndex + 1
|
||||
refreshState = 0
|
||||
calibrationState = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[4]
|
||||
if field[2] == COMBO and #field == 6 then
|
||||
value = field[6][1 + value]
|
||||
elseif field[2] == VALUE and #field == 8 then
|
||||
value = value + field[8] - field[5]
|
||||
end
|
||||
modifications[#modifications + 1] = { field[3], value }
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
if fields[current][4] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage(event)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function runConfigPage(event)
|
||||
fields = configFields
|
||||
local result = runFieldsPage(event)
|
||||
if LCD_W == 128 then
|
||||
local mountText = { "Label is facing the sky", "Label is facing ground", "Label is left when", "Label is right when" }
|
||||
if fields[2][4] ~= nil then
|
||||
lcd.drawText(1, 30, "Pins toward tail")
|
||||
lcd.drawText(1, 40, mountText[1 + fields[2][4]])
|
||||
if fields[2][4] > 1 then
|
||||
lcd.drawText(1, 50, "looking from the tail")
|
||||
end
|
||||
end
|
||||
else
|
||||
if fields[1][4] ~= nil then
|
||||
if LCD_W == 480 then
|
||||
if wingBitmaps[1 + fields[1][4]] == nil then
|
||||
wingBitmaps[1 + fields[1][4]] = Bitmap.open(wingBitmapsFile[1 + fields[1][4]])
|
||||
end
|
||||
lcd.drawBitmap(wingBitmaps[1 + fields[1][4]], 10, 90)
|
||||
else
|
||||
lcd.drawPixmap(20, 28, wingBitmapsFile[1 + fields[1][4]])
|
||||
end
|
||||
end
|
||||
if fields[2][4] ~= nil then
|
||||
if LCD_W == 480 then
|
||||
if mountBitmaps[1 + fields[2][4]] == nil then
|
||||
mountBitmaps[1 + fields[2][4]] = Bitmap.open(mountBitmapsFile[1 + fields[2][4]])
|
||||
end
|
||||
lcd.drawBitmap(mountBitmaps[1 + fields[2][4]], 190, 110)
|
||||
else
|
||||
lcd.drawPixmap(128, 28, mountBitmapsFile[1 + fields[2][4]])
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function runSettingsPage(event)
|
||||
fields = settingsFields
|
||||
return runFieldsPage(event)
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit, refreshState, refreshIndex = 1, false, 0, 0
|
||||
if LCD_W == 480 then
|
||||
margin = 10
|
||||
spacing = 20
|
||||
wingBitmapsFile = { "/SCRIPTS/TOOLS/img/plane_b.png", "/SCRIPTS/TOOLS/img/delta_b.png", "/SCRIPTS/TOOLS/img/planev_b.png" }
|
||||
mountBitmapsFile = { "/SCRIPTS/TOOLS/img/up.png", "/SCRIPTS/TOOLS/img/down.png", "/SCRIPTS/TOOLS/img/vert.png", "/SCRIPTS/TOOLS/img/vert-r.png" }
|
||||
end
|
||||
pages = {
|
||||
runConfigPage,
|
||||
runSettingsPage,
|
||||
}
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
selectPage(1)
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
||||
killEvents(event);
|
||||
selectPage(-1)
|
||||
end
|
||||
|
||||
local result = pages[page](event)
|
||||
refreshNext()
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return { init = init, run = run }
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # 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. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
|
||||
--###############################################################################
|
||||
-- Multi buffer for HoTT description
|
||||
-- To start operation:
|
||||
-- Write "HoTT" at address 0..3
|
||||
-- Write 0xFF at address 4 will request the buffer to be cleared
|
||||
-- Write 0x0F at address 5
|
||||
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
|
||||
-- by 8 lines
|
||||
-- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
|
||||
-- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
|
||||
-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
|
||||
-- Write at address 4 the value 0xFF will request the buffer to be cleared
|
||||
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
|
||||
--###############################################################################
|
||||
|
||||
HoTT_Sensor = 0
|
||||
Timer_128 = 100
|
||||
|
||||
local function HoTT_Release()
|
||||
multiBuffer( 0, 0 )
|
||||
end
|
||||
|
||||
local function HoTT_Send(button)
|
||||
multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
|
||||
end
|
||||
|
||||
local function HoTT_Sensor_Inc()
|
||||
local detected_sensors=multiBuffer( 4 )
|
||||
local a
|
||||
if detected_sensors ~= 0xFF then
|
||||
repeat
|
||||
HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
|
||||
if HoTT_Sensor ~= 0 then
|
||||
a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
|
||||
end
|
||||
until HoTT_Sensor==0 or a % 2 == 1
|
||||
HoTT_Send( 0x0F )
|
||||
end
|
||||
end
|
||||
|
||||
local function HoTT_Draw_LCD()
|
||||
local i
|
||||
local value
|
||||
local line
|
||||
local result
|
||||
local offset=0
|
||||
|
||||
local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
|
||||
|
||||
lcd.clear()
|
||||
|
||||
if LCD_W == 480 then
|
||||
--Draw title
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
|
||||
--Draw RX Menu
|
||||
if multiBuffer( 4 ) == 0xFF then
|
||||
lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
|
||||
else
|
||||
for line = 0, 7, 1 do
|
||||
for i = 0, 21-1, 1 do
|
||||
value=multiBuffer( line*21+6+i )
|
||||
if value > 0x80 then
|
||||
value = value - 0x80
|
||||
lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
|
||||
else
|
||||
lcd.drawText(10+i*16,32+20*line,string.char(value))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
--Draw RX Menu on LCD_W=128
|
||||
if multiBuffer( 4 ) == 0xFF then
|
||||
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
|
||||
else
|
||||
if Timer_128 ~= 0 then
|
||||
--Intro page
|
||||
Timer_128 = Timer_128 - 1
|
||||
lcd.drawScreenTitle("Graupner Hott",0,0)
|
||||
lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
|
||||
lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
|
||||
else
|
||||
--Menu page
|
||||
for line = 0, 7, 1 do
|
||||
for i = 0, 21-1, 1 do
|
||||
value=multiBuffer( line*21+6+i )
|
||||
if value > 0x80 then
|
||||
value = value - 0x80
|
||||
lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
|
||||
else
|
||||
lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function HoTT_Init()
|
||||
--Set protocol to talk to
|
||||
multiBuffer( 0, string.byte('H') )
|
||||
--test if value has been written
|
||||
if multiBuffer( 0 ) ~= string.byte('H') then
|
||||
error("Not enough memory!")
|
||||
return 2
|
||||
end
|
||||
multiBuffer( 1, string.byte('o') )
|
||||
multiBuffer( 2, string.byte('T') )
|
||||
multiBuffer( 3, string.byte('T') )
|
||||
--Request init of the RX buffer
|
||||
multiBuffer( 4, 0xFF )
|
||||
--Request RX to send the config menu
|
||||
HoTT_Send( 0x0F )
|
||||
HoTT_Sensor = 0;
|
||||
HoTT_Detected_Sensors=0;
|
||||
Timer_128 = 100
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function HoTT_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
HoTT_Release()
|
||||
return 2
|
||||
else
|
||||
if event == EVT_VIRTUAL_PREV_PAGE then
|
||||
killEvents(event)
|
||||
HoTT_Send( 0x07 )
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
HoTT_Send( 0x09 )
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
HoTT_Send( 0x0B )
|
||||
elseif event == EVT_VIRTUAL_NEXT then
|
||||
HoTT_Send( 0x0D )
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
HoTT_Send( 0x0E )
|
||||
elseif event == EVT_VIRTUAL_MENU then
|
||||
Timer_128 = 100
|
||||
HoTT_Sensor_Inc()
|
||||
else
|
||||
HoTT_Send( 0x0F )
|
||||
end
|
||||
HoTT_Draw_LCD()
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return { init=HoTT_Init, run=HoTT_Run }
|
||||
@@ -1,192 +0,0 @@
|
||||
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
|
||||
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
|
||||
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
|
||||
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
|
||||
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||
14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||
59,1,BayangRX,CPPM,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
|
||||
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
|
||||
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
|
||||
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
|
||||
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
|
||||
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
|
||||
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
|
||||
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
|
||||
12,0,CX10,Green,1,Flip,Rate
|
||||
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
|
||||
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
|
||||
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
|
||||
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
|
||||
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
|
||||
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
|
||||
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
7,3,Devo,6CH,0,CH5,CH6
|
||||
7,4,Devo,7CH,0,CH5,CH6,CH7
|
||||
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
|
||||
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
|
||||
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
|
||||
16,0,ESKY,Std,0,Gyro,Pitch
|
||||
16,1,ESKY,ET4,0,Gyro,Pitch
|
||||
35,0,ESKY150,4CH,0
|
||||
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
|
||||
69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
|
||||
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
|
||||
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
|
||||
1,3,Flysky,V912,1,BtmBtn,TopBtn
|
||||
1,4,Flysky,CX20,0,CH5,CH6,CH7
|
||||
28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
53,0,Height,5ch,0,Gear
|
||||
53,1,Height,8ch,0,Gear,Gyro,Flap,Light
|
||||
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
|
||||
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
|
||||
3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
|
||||
67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
67,1,FrSkyL,LR12_6CH,0,CH5,CH6
|
||||
15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||
15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
|
||||
15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
15,5,FrSkyX,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||
64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
|
||||
64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
|
||||
65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
|
||||
55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
55,1,FrSkyRX,CloneTX,0
|
||||
55,2,FrSkyRX,EraseTX,0
|
||||
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
58,0,FX816,P38,1
|
||||
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||
32,0,GW008,FY326,1,Flip
|
||||
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
|
||||
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
|
||||
4,1,Hisky,HK310,0,Aux
|
||||
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
|
||||
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
|
||||
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
|
||||
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
|
||||
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
|
||||
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
|
||||
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
49,0,KF606,Std,1,Trim
|
||||
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||
17,5,MT99XX,A180,0,3D_6G
|
||||
17,6,MT99XX,Dragon,0,Mode,RTH
|
||||
44,0,NCC1701,Std,1,Warp
|
||||
77,0,OMP,M2,0,THold,IdleUp,6G_3D
|
||||
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||
60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
|
||||
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
|
||||
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
|
||||
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
|
||||
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
|
||||
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
|
||||
31,2,Q303,CX10D,1,Arm,Flip
|
||||
31,3,Q303,CX10WD,1,Arm,Flip
|
||||
72,0,Q90C,Std,0,FMode,VTX+
|
||||
74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
|
||||
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||
21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8
|
||||
19,0,Shenqi,Cycle,1
|
||||
68,0,Skyartec,Std,0,CH5,CH6,CH7
|
||||
11,0,SLT,V1,0,Gear,Pitch
|
||||
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
|
||||
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
|
||||
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
|
||||
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
|
||||
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
|
||||
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
|
||||
61,0,Tiger,Std,1,Flip,Light
|
||||
43,0,Traxxas,6519,0
|
||||
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
|
||||
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
|
||||
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
|
||||
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
|
||||
46,0,V911s,V911s,1,Calib
|
||||
46,1,V911s,E119,1,Calib
|
||||
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
|
||||
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
|
||||
30,1,WK2x01,WK2401,0
|
||||
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
|
||||
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
|
||||
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
|
||||
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
|
||||
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
|
||||
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
|
||||
52,0,ZSX,280,1,Light
|
||||
78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
79,0,WFLY2,RF20x,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||
80,0,E016Hv2,E016Hv2,1,TakLan,EmStop,Flip,Calib,HLess,RTH
|
||||
81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE
|
||||
82,0,LOLI,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe
|
||||
83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR
|
||||
84,0,JOYSWAY,Std,0
|
||||
85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH
|
||||
@@ -1,311 +0,0 @@
|
||||
|
||||
local toolName = "TNS|Multi chan namer|TNE"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local protocol_name = ""
|
||||
local sub_protocol_name = ""
|
||||
local bind_ch = 0
|
||||
local module_conf = {}
|
||||
local module_pos = "Internal"
|
||||
local file_ok = 0
|
||||
local done = 0
|
||||
local protocol = 0
|
||||
local sub_protocol = 0
|
||||
local f_seek = 0
|
||||
local channel_names={}
|
||||
local num_search = "Searching"
|
||||
|
||||
local function drawScreenTitle(title)
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function bitand(a, b)
|
||||
local result = 0
|
||||
local bitval = 1
|
||||
while a > 0 and b > 0 do
|
||||
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
|
||||
result = result + bitval -- set the current bit
|
||||
end
|
||||
bitval = bitval * 2 -- shift left
|
||||
a = math.floor(a/2) -- shift right
|
||||
b = math.floor(b/2)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function Multi_Draw_LCD(event)
|
||||
local line = 0
|
||||
|
||||
lcd.clear()
|
||||
drawScreenTitle("Multi channels namer")
|
||||
|
||||
--Display settings
|
||||
local lcd_opt = 0
|
||||
if LCD_W == 480 then
|
||||
x_pos = 10
|
||||
y_pos = 32
|
||||
y_inc = 20
|
||||
else
|
||||
x_pos = 0
|
||||
y_pos = 9
|
||||
y_inc = 8
|
||||
lcd_opt = SMLSIZE
|
||||
end
|
||||
|
||||
--Multi Module detection
|
||||
if module_conf["Type"] ~= 6 then
|
||||
if LCD_W == 480 then
|
||||
lcd.drawText(10,50,"No Multi module configured...", BLINK)
|
||||
else
|
||||
--Draw on LCD_W=128
|
||||
lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
|
||||
end
|
||||
return
|
||||
else
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
--Channel order
|
||||
if (ch_order == -1) then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
--Can't open file MultiChan.txt
|
||||
if file_ok == 0 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
|
||||
return
|
||||
end
|
||||
|
||||
if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
|
||||
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||
if f == nil then return end
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
|
||||
num_search = num_search .. "."
|
||||
if #num_search > 15 then
|
||||
num_search = string.sub(num_search,1,9)
|
||||
end
|
||||
local proto = 0
|
||||
local sub_proto = 0
|
||||
local proto_name = ""
|
||||
local sub_proto_name = ""
|
||||
local channels = ""
|
||||
local nbr_try = 0
|
||||
local nbr_car = 0
|
||||
repeat
|
||||
io.seek(f, f_seek)
|
||||
local data = io.read(f, 100) -- read 100 characters
|
||||
if #data ==0 then
|
||||
f_seek = -1 -- end of file
|
||||
break
|
||||
end
|
||||
proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
|
||||
if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
|
||||
if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
|
||||
protocol_name = proto_name
|
||||
sub_protocol_name = sub_proto_name
|
||||
bind_ch = tonumber(bind_ch)
|
||||
if channels ~= nil then
|
||||
--extract channel names
|
||||
nbr_car = string.find(channels, "\r")
|
||||
if nbr_car == nil then nbr_car = string.find(channels, "\n") end
|
||||
if nbr_car ~= nil then
|
||||
channels = string.sub(channels,1,nbr_car-1)
|
||||
end
|
||||
local i = 5
|
||||
for k in string.gmatch(channels, ",([%w-_ ]+)") do
|
||||
channel_names[i] = k
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
f_seek = -1 -- protocol found
|
||||
break
|
||||
end
|
||||
end
|
||||
if f_seek ~= -1 then
|
||||
nbr_car = string.find(data, "\n")
|
||||
if nbr_car == nil then nbr_car = string.find(data, "\r") end
|
||||
if nbr_car == nil then
|
||||
f_seek = -1 -- end of file
|
||||
break
|
||||
end
|
||||
f_seek = f_seek + nbr_car -- seek to next line
|
||||
nbr_try = nbr_try + 1
|
||||
end
|
||||
until nbr_try > 20 or f_seek == -1
|
||||
io.close(f)
|
||||
end
|
||||
|
||||
if f_seek ~= -1 then
|
||||
return -- continue searching...
|
||||
end
|
||||
|
||||
--Protocol & Sub_protocol
|
||||
if protocol_name == "" or sub_protocol_name == "" then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
|
||||
return
|
||||
elseif LCD_W > 128 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||
line = line + 1
|
||||
else
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
|
||||
line = line + 1
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
text1=""
|
||||
text2=""
|
||||
for i,v in ipairs(channel_names) do
|
||||
if i<=8 then
|
||||
if i==1 then
|
||||
text1 = v
|
||||
else
|
||||
text1=text1 .. "," .. v
|
||||
end
|
||||
else
|
||||
if i==9 then
|
||||
text2 = v
|
||||
else
|
||||
text2=text2 .. "," .. v
|
||||
end
|
||||
end
|
||||
end
|
||||
if LCD_W > 128 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
|
||||
line = line + 1
|
||||
if text2 ~= "" then
|
||||
lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
end
|
||||
|
||||
if event ~= EVT_VIRTUAL_ENTER and done == 0 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"<ENT> Save", lcd_opt + INVERS + BLINK)
|
||||
return
|
||||
end
|
||||
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
|
||||
line = line + 1
|
||||
local output, nbr
|
||||
if done == 0 then
|
||||
for i,v in ipairs(channel_names) do
|
||||
output = model.getOutput(i-1)
|
||||
output["name"] = v
|
||||
model.setOutput(i-1,output)
|
||||
nbr = i
|
||||
end
|
||||
for i = nbr, 15 do
|
||||
output = model.getOutput(i)
|
||||
output["name"] = "n-a"
|
||||
model.setOutput(i,output)
|
||||
end
|
||||
if bind_ch == 1 then
|
||||
output = model.getOutput(15)
|
||||
output["name"] = "BindCH"
|
||||
model.setOutput(15,output)
|
||||
end
|
||||
done = 1
|
||||
end
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function Multi_Init()
|
||||
module_conf = model.getModule(0)
|
||||
if module_conf["Type"] ~= 6 then
|
||||
module_pos = "External"
|
||||
module_conf = model.getModule(1)
|
||||
if module_conf["Type"] ~= 6 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
protocol = module_conf["protocol"]
|
||||
sub_protocol = module_conf["subProtocol"]
|
||||
|
||||
--Exceptions on first 4 channels...
|
||||
local stick_names = { "Rud", "Ele", "Thr", "Ail" }
|
||||
if ( protocol == 4 and sub_protocol == 1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
|
||||
stick_names[2] = "n-a"
|
||||
stick_names[4] = "n-a"
|
||||
elseif protocol == 43 then -- Traxxas
|
||||
stick_names[2] = "Aux4"
|
||||
stick_names[4] = "Aux3"
|
||||
elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
|
||||
stick_names[4] = "n-a"
|
||||
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
|
||||
stick_names[1] = "n-a"
|
||||
stick_names[2] = "n-a"
|
||||
end
|
||||
|
||||
--Determine fist 4 channels order
|
||||
local ch_order=module_conf["channelsOrder"]
|
||||
if (ch_order == -1) then
|
||||
channel_names[1] = stick_names[defaultChannel(0)+1]
|
||||
channel_names[2] = stick_names[defaultChannel(1)+1]
|
||||
channel_names[3] = stick_names[defaultChannel(2)+1]
|
||||
channel_names[4] = stick_names[defaultChannel(3)+1]
|
||||
else
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[4]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[2]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[3]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[1]
|
||||
end
|
||||
|
||||
--Exceptions on first 4 channels...
|
||||
if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
|
||||
channel_names[1] = "ST"
|
||||
channel_names[2] = "THR"
|
||||
channel_names[3] = "CH3"
|
||||
channel_names[4] = "CH4"
|
||||
end
|
||||
|
||||
--Check MultiChan.txt
|
||||
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||
if f == nil then return end
|
||||
file_ok = 1
|
||||
io.close(f)
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function Multi_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
else
|
||||
Multi_Draw_LCD(event)
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
return { init=Multi_Init, run=Multi_Run }
|
||||
@@ -1,221 +0,0 @@
|
||||
|
||||
local toolName = "TNS|Multi LOLI RX config|TNE"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local loli_nok = false
|
||||
local channels={ { 768, "PWM", 100, 102, "PPM", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH1
|
||||
{ 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH2
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH3
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH4
|
||||
{ 102, "SBUS", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH5
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH6
|
||||
{ 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH7
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 } } -- CH8
|
||||
|
||||
local sel = 1
|
||||
local edit = false
|
||||
|
||||
local blink = 0
|
||||
local BLINK_SPEED = 15
|
||||
|
||||
local function drawScreenTitle(title)
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function LOLI_Draw_LCD(event)
|
||||
local line = 0
|
||||
|
||||
lcd.clear()
|
||||
|
||||
--Display settings
|
||||
local lcd_opt = 0
|
||||
if LCD_W == 480 then
|
||||
drawScreenTitle("Multi - LOLI RX configuration tool")
|
||||
x_pos = 152
|
||||
x_inc = 90
|
||||
y_pos = 40
|
||||
y_inc = 20
|
||||
else
|
||||
x_pos = 5
|
||||
x_inc = 30
|
||||
y_pos = 1
|
||||
y_inc = 8
|
||||
lcd_opt = SMLSIZE
|
||||
end
|
||||
|
||||
--Multi Module detection
|
||||
if loli_nok then
|
||||
if LCD_W == 480 then
|
||||
lcd.drawText(10,50,"The LOLI protocol is not selected...", lcd_opt)
|
||||
else
|
||||
--Draw on LCD_W=128
|
||||
lcd.drawText(2,17,"LOLI protocol not selected...",SMLSIZE)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
--Display current config
|
||||
if LCD_W == 480 then
|
||||
line = line + 1
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line -2, "Channel", lcd_opt)
|
||||
lcd.drawText(x_pos+x_inc, y_pos+y_inc*line -2, "Function", lcd_opt)
|
||||
lcd.drawRectangle(x_pos-4, y_pos+y_inc*line -4 , 2*x_inc +2, 188)
|
||||
lcd.drawLine(x_pos-4, y_pos+y_inc*line +18, x_pos-4 +2*x_inc +1, y_pos+y_inc*line +18, SOLID, 0)
|
||||
lcd.drawLine(x_pos+x_inc -5, y_pos+y_inc*line -4, x_pos+x_inc -5, y_pos+y_inc*line -5 +188, SOLID, 0)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
local out
|
||||
for i = 1, 8 do
|
||||
out = getValue("ch"..(i+8))
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line, "CH"..i, lcd_opt)
|
||||
for j = 1, #channels[i], 3 do
|
||||
if out > channels[i][j] then
|
||||
if sel == i then
|
||||
invert = INVERS
|
||||
if edit == true then
|
||||
blink = blink + 1
|
||||
if blink > BLINK_SPEED then
|
||||
invert = 0
|
||||
if blink > BLINK_SPEED * 2 then
|
||||
blink = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
invert = 0
|
||||
end
|
||||
lcd.drawText(x_pos+x_inc, y_pos+y_inc*line, channels[i][j+1], lcd_opt + invert)
|
||||
break
|
||||
end
|
||||
end
|
||||
line = line + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function LOLI_Change_Value(dir)
|
||||
local pos = 0
|
||||
local out
|
||||
--look for the current position
|
||||
out = getValue("ch"..(sel+8))
|
||||
for j = 1, #channels[sel], 3 do
|
||||
if out > channels[sel][j] then
|
||||
pos = j
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--decrement or increment
|
||||
if dir < 0 and pos > 1 then
|
||||
pos = pos - 3
|
||||
elseif dir > 0 and pos + 3 < #channels[sel] then
|
||||
pos = pos + 3
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
--delete all mixers for the selected channel
|
||||
local num_mix = model.getMixesCount(sel-1 +8)
|
||||
for i = 1, num_mix do
|
||||
model.deleteMix(sel-1 +8, 0);
|
||||
end
|
||||
|
||||
--create new mixer
|
||||
local source_max = getFieldInfo("cyc1")
|
||||
|
||||
local val = { name = channels[sel][pos+1],
|
||||
source = source_max.id - 1, -- MAX=100 on TX16S
|
||||
weight = channels[sel][pos+2],
|
||||
offset = 0,
|
||||
switch = 0,
|
||||
multiplex = 0,
|
||||
curveType = 0,
|
||||
curveValue = 0,
|
||||
flightModes = 0,
|
||||
carryTrim = false,
|
||||
mixWarn = 0,
|
||||
delayUp = 0,
|
||||
delayDown = 0,
|
||||
speedUp = 0,
|
||||
speedDown = 0 }
|
||||
model.insertMix(sel-1 +8, 0, val)
|
||||
end
|
||||
|
||||
local function LOLI_Menu(event)
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
if edit == false then
|
||||
-- not changing a value
|
||||
if sel < 8 then
|
||||
sel = sel + 1
|
||||
end
|
||||
else
|
||||
-- need to inc the value
|
||||
LOLI_Change_Value(1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
if edit == false then
|
||||
-- not changing a value
|
||||
if sel > 1 then
|
||||
sel = sel - 1
|
||||
end
|
||||
else
|
||||
-- need to dec the value
|
||||
LOLI_Change_Value(-1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
if edit == false then
|
||||
edit = true
|
||||
blink = BLINK_SPEED
|
||||
else
|
||||
edit = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function LOLI_Init()
|
||||
local module_conf = model.getModule(0)
|
||||
if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then
|
||||
module_conf = model.getModule(1)
|
||||
if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then
|
||||
loli_nok = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function LOLI_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
else
|
||||
LOLI_Menu(event)
|
||||
LOLI_Draw_LCD(event)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return { init=LOLI_Init, run=LOLI_Run }
|
||||
@@ -1,42 +0,0 @@
|
||||
local toolName = "TNS|Crossfire configure|TNE"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
end
|
||||
|
||||
-- Run
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot run as a model script!")
|
||||
return 2
|
||||
end
|
||||
|
||||
if crossfireTelemetryPush() == nil then
|
||||
error("Crossfire not available!")
|
||||
return 2
|
||||
end
|
||||
|
||||
chdir("/SCRIPTS/TOOLS/CROSSFIRE")
|
||||
return "crossfire.lua"
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 10 KiB |
@@ -1 +0,0 @@
|
||||
Scripts that need to be available in TOOLS menu should be in this directory
|
||||
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 659 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 506 B |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,478 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
|
||||
-- load common Bitmaps
|
||||
local ImgMarkBg = Bitmap.open("img/mark_bg.png")
|
||||
local BackgroundImg = Bitmap.open("img/background.png")
|
||||
local ImgPlane = Bitmap.open("img/plane.png")
|
||||
local ImgPageUp = Bitmap.open("img/pageup.png")
|
||||
local ImgPageDn = Bitmap.open("img/pagedn.png")
|
||||
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[3] == VALUE then
|
||||
min = field[6]
|
||||
max = field[7]
|
||||
elseif field[3] == COMBO then
|
||||
min = 0
|
||||
max = #(field[6]) - 1
|
||||
end
|
||||
if (step < 0 and field[5] > min) or (step > 0 and field[5] < max) then
|
||||
field[5] = field[5] + step
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
page = 1 + ((page + step - 1 + #pages) % #pages)
|
||||
edit = false
|
||||
current = 1
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
repeat
|
||||
current = 1 + ((current + step - 1 + #fields) % #fields)
|
||||
until fields[current][4]==1
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage(event)
|
||||
|
||||
for index = 1, 10, 1 do
|
||||
local field = fields[index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local attr = current == (index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
attr = attr + DEFAULT_COLOR
|
||||
|
||||
if field[4] == 1 then
|
||||
if field[3] == VALUE then
|
||||
lcd.drawNumber(field[1], field[2], field[5], LEFT + attr)
|
||||
elseif field[3] == COMBO then
|
||||
if field[5] >= 0 and field[5] < #(field[6]) then
|
||||
lcd.drawText(field[1],field[2], field[6][1+field[5]], attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[5]
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
if fields[current][5] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage(event)
|
||||
return 0
|
||||
end
|
||||
|
||||
-- set visibility flags starting with SECOND field of fields
|
||||
local function setFieldsVisible(...)
|
||||
local arg={...}
|
||||
local cnt = 2
|
||||
for i,v in ipairs(arg) do
|
||||
fields[cnt][4] = v
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- draws one letter mark
|
||||
local function drawMark(x, y, name)
|
||||
lcd.drawBitmap(ImgMarkBg, x, y)
|
||||
lcd.drawText(x+8, y+3, name, DEFAULT_COLOR)
|
||||
end
|
||||
|
||||
|
||||
local MotorFields = {
|
||||
{50, 50, COMBO, 1, 1, { "No", "Yes"} },
|
||||
{50, 127, COMBO, 1, 2, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local ImgEngine
|
||||
|
||||
local function runMotorConfig(event)
|
||||
lcd.clear()
|
||||
if ImgEngine == nil then
|
||||
ImgEngine = Bitmap.open("img/prop.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
lcd.drawBitmap(ImgEngine, 310, 50)
|
||||
fields = MotorFields
|
||||
lcd.drawText(40, 20, "Does your model have a motor ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 200, 30, TEXT_BGCOLOR)
|
||||
fields[2][4]=0
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawText(40, 100, "What channel is it on ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
fields[2][4]=1
|
||||
end
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
-- fields format : {[1]x, [2]y, [3]COMBO, [4]visible, [5]default, [6]{values}}
|
||||
-- fields format : {[1]x, [2]y, [3]VALUE, [4]visible, [5]default, [6]min, [7]max}
|
||||
local AilFields = {
|
||||
{50, 50, COMBO, 1, 2, { "None", "One, or two with Y cable", "Two"} },
|
||||
{50, 127, COMBO, 1, 0, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, -- Ail1 chan
|
||||
{50, 167, COMBO, 1, 4, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, -- Ail2 chan
|
||||
}
|
||||
|
||||
local ImgAilR
|
||||
local ImgAilL
|
||||
|
||||
local function runAilConfig(event)
|
||||
lcd.clear()
|
||||
if ImgAilR == nil then
|
||||
ImgAilR = Bitmap.open("img/rail.png")
|
||||
ImgAilL = Bitmap.open("img/lail.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
lcd.drawBitmap(ImgPlane, 252, 100)
|
||||
fields = AilFields
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawBitmap(ImgAilR, 274, 123)
|
||||
lcd.drawBitmap(ImgAilL, 395, 235)
|
||||
drawMark(308, 115, "A")
|
||||
drawMark(422, 220, "A")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
setFieldsVisible(1, 0)
|
||||
elseif fields[1][5] == 2 then
|
||||
lcd.drawBitmap(ImgAilR, 274, 123)
|
||||
lcd.drawBitmap(ImgAilL, 395, 235)
|
||||
drawMark(308, 115, "A")
|
||||
drawMark(422, 220, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1)
|
||||
else
|
||||
setFieldsVisible(0, 0)
|
||||
end
|
||||
lcd.drawText(40, 20, "Number of ailerons on your model ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local FlapsFields = {
|
||||
{50, 50, COMBO, 1, 0, { "No", "Yes, on one channel", "Yes, on two channels"} },
|
||||
{50, 127, COMBO, 1, 6, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
{50, 167, COMBO, 1, 7, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local ImgFlp
|
||||
|
||||
local function runFlapsConfig(event)
|
||||
lcd.clear()
|
||||
if ImgFlp == nil then
|
||||
ImgFlp = Bitmap.open("img/flap.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
lcd.drawBitmap(ImgPlane, 252, 100)
|
||||
fields = FlapsFields
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawBitmap(ImgFlp, 315, 160)
|
||||
lcd.drawBitmap(ImgFlp, 358, 202)
|
||||
drawMark(332, 132, "A")
|
||||
drawMark(412, 215, "A")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
setFieldsVisible(1, 0)
|
||||
elseif fields[1][5] == 2 then
|
||||
lcd.drawBitmap(ImgFlp, 315, 160)
|
||||
lcd.drawBitmap(ImgFlp, 358, 202)
|
||||
drawMark(332, 132, "A")
|
||||
drawMark(412, 215, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1)
|
||||
else
|
||||
setFieldsVisible(0, 0)
|
||||
end
|
||||
lcd.drawText(40, 20, "Does your model have flaps ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local TailFields = {
|
||||
{50, 50, COMBO, 1, 1, { "1 channel for Elevator, no Rudder", "One channel for Elevator, one for Rudder", "Two channels for Elevator, one for Rudder", "V Tail"} },
|
||||
{50, 127, COMBO, 1, 1, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, --ele
|
||||
{50, 167, COMBO, 1, 3, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, --rud
|
||||
{50, 207, COMBO, 0, 5, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, --ele2
|
||||
}
|
||||
|
||||
local ImgTail
|
||||
local ImgVTail
|
||||
local ImgTailRud
|
||||
|
||||
local function runTailConfig(event)
|
||||
lcd.clear()
|
||||
if ImgTail == nil then
|
||||
ImgTail = Bitmap.open("img/tail.png")
|
||||
ImgVTail = Bitmap.open("img/vtail.png")
|
||||
ImgTailRud = Bitmap.open("img/tailrud.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = TailFields
|
||||
if fields[1][5] == 0 then
|
||||
lcd.drawBitmap(ImgTail, 252, 100)
|
||||
drawMark(360, 125, "A")
|
||||
drawMark(390, 155, "A")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
setFieldsVisible(1, 0, 0)
|
||||
end
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawBitmap(ImgTail, 252, 100)
|
||||
lcd.drawBitmap(ImgTailRud, 340, 100)
|
||||
drawMark(415, 150, "A")
|
||||
drawMark(380, 120, "A")
|
||||
drawMark(390, 185, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1, 0)
|
||||
end
|
||||
if fields[1][5] == 2 then
|
||||
lcd.drawBitmap(ImgTail, 252, 100)
|
||||
lcd.drawBitmap(ImgTailRud, 340, 100)
|
||||
drawMark(415, 150, "C")
|
||||
drawMark(380, 120, "A")
|
||||
drawMark(390, 185, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
lcd.drawFilledRectangle(40, 202, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 204, "C")
|
||||
setFieldsVisible(1, 1, 1)
|
||||
end
|
||||
if fields[1][5] == 3 then
|
||||
lcd.drawBitmap(ImgVTail, 252, 100)
|
||||
drawMark(315, 110, "A")
|
||||
drawMark(382, 120, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1, 0)
|
||||
end
|
||||
lcd.drawText(40, 20, "Pick the tail config of your model", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local lineIndex
|
||||
local function drawNextLine(text, text2)
|
||||
lcd.drawText(40, lineIndex, text, DEFAULT_COLOR)
|
||||
lcd.drawText(242, lineIndex, ": CH" .. text2 + 1, DEFAULT_COLOR)
|
||||
lineIndex = lineIndex + 20
|
||||
end
|
||||
|
||||
local ConfigSummaryFields = {
|
||||
{110, 250, COMBO, 1, 0, { "No, I need to change something", "Yes, all is well, create the plane !"} },
|
||||
}
|
||||
|
||||
local ImgSummary
|
||||
|
||||
local function runConfigSummary(event)
|
||||
lcd.clear()
|
||||
if ImgSummary == nil then
|
||||
ImgSummary = Bitmap.open("img/summary.png")
|
||||
end
|
||||
fields = ConfigSummaryFields
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgSummary, 300, 60)
|
||||
lineIndex = 40
|
||||
-- motors
|
||||
if(MotorFields[1][5] == 1) then
|
||||
drawNextLine("Motor channel", MotorFields[2][5])
|
||||
end
|
||||
-- ail
|
||||
if(AilFields[1][5] == 1) then
|
||||
drawNextLine("Aileron channel",AilFields[2][5])
|
||||
elseif (AilFields[1][5] == 2) then
|
||||
drawNextLine("Aileron Right channel",AilFields[2][5])
|
||||
drawNextLine("Aileron Left channel",AilFields[3][5])
|
||||
end
|
||||
-- flaps
|
||||
if(FlapsFields[1][5] == 1) then
|
||||
drawNextLine("Flaps channel",FlapsFields[2][5])
|
||||
elseif (FlapsFields[1][5] == 2) then
|
||||
drawNextLine("Flaps Right channel",FlapsFields[2][5])
|
||||
drawNextLine("Flaps Left channel",FlapsFields[3][5])
|
||||
end
|
||||
-- tail
|
||||
if(TailFields[1][5] == 0) then
|
||||
drawNextLine("Elevator channel",TailFields[2][5])
|
||||
elseif (TailFields[1][5] == 1) then
|
||||
drawNextLine("Elevator channel",TailFields[2][5])
|
||||
drawNextLine("Rudder channel",TailFields[3][5])
|
||||
elseif (TailFields[1][5] == 2) then
|
||||
drawNextLine("Elevator Right channel",TailFields[2][5])
|
||||
drawNextLine("Rudder channel",TailFields[3][5])
|
||||
drawNextLine("Elevator Left channel",TailFields[4][5])
|
||||
elseif (TailFields[1][5] == 3) then
|
||||
drawNextLine("V-Tail Right", TailFields[2][5])
|
||||
drawNextLine("V-Tail Left", TailFields[3][5])
|
||||
end
|
||||
local result = runFieldsPage(event)
|
||||
if(fields[1][5] == 1 and edit == false) then
|
||||
selectPage(1)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function addMix(channel, input, name, weight, index)
|
||||
local mix = { source=input, name=name }
|
||||
if weight ~= nil then
|
||||
mix.weight = weight
|
||||
end
|
||||
if index == nil then
|
||||
index = 0
|
||||
end
|
||||
model.insertMix(channel, index, mix)
|
||||
end
|
||||
|
||||
local function createModel(event)
|
||||
lcd.clear()
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgSummary, 300, 60)
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
-- motor
|
||||
if(MotorFields[1][5] == 1) then
|
||||
addMix(MotorFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(2), "Motor")
|
||||
end
|
||||
-- Ailerons
|
||||
if(AilFields[1][5] == 1) then
|
||||
addMix(AilFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "Ail")
|
||||
elseif (AilFields[1][5] == 2) then
|
||||
addMix(AilFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "AilR")
|
||||
addMix(AilFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "AilL", -100)
|
||||
end
|
||||
-- Flaps
|
||||
if(FlapsFields[1][5] == 1) then
|
||||
addMix(FlapsFields[2][5], MIXSRC_SA, "Flaps")
|
||||
elseif (FlapsFields[1][5] == 2) then
|
||||
addMix(FlapsFields[2][5], MIXSRC_SA, "FlapsR")
|
||||
addMix(FlapsFields[3][5], MIXSRC_SA, "FlapsL")
|
||||
end
|
||||
-- Tail
|
||||
if(TailFields[1][5] == 0) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "Elev")
|
||||
elseif (TailFields[1][5] == 1) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "Elev")
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder")
|
||||
elseif (TailFields[1][5] == 2) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "ElevR")
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder")
|
||||
addMix(TailFields[4][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "ElevL")
|
||||
elseif (TailFields[1][5] == 3) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "V-EleR", 50)
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "V-RudR", 50, 1)
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "V-EleL", 50)
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "V-RudL", -50, 1)
|
||||
end
|
||||
lcd.drawText(70, 90, "Model successfully created !", DEFAULT_COLOR)
|
||||
lcd.drawText(100, 130, "Press RTN to exit", DEFAULT_COLOR)
|
||||
return 2
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit = 1, false
|
||||
pages = {
|
||||
runMotorConfig,
|
||||
runAilConfig,
|
||||
runFlapsConfig,
|
||||
runTailConfig,
|
||||
runConfigSummary,
|
||||
createModel,
|
||||
}
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE and page < #pages-1 then
|
||||
selectPage(1)
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE and page > 1 then
|
||||
killEvents(event);
|
||||
selectPage(-1)
|
||||
end
|
||||
|
||||
local result = pages[page](event)
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 506 B |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 77 KiB |
@@ -1,411 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
-----# Credits: graphics by Radiomaster #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
local switches = {"SA", "SB", "SC", "SD", "SE", "SF", "SG"}
|
||||
|
||||
-- load common Bitmaps
|
||||
local ImgMarkBg = Bitmap.open("img/mark_bg.png")
|
||||
local BackgroundImg = Bitmap.open("img/background.png")
|
||||
local ImgPageUp = Bitmap.open("img/pageup.png")
|
||||
local ImgPageDn = Bitmap.open("img/pagedn.png")
|
||||
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[3] == VALUE then
|
||||
min = field[6]
|
||||
max = field[7]
|
||||
elseif field[3] == COMBO then
|
||||
min = 0
|
||||
max = #(field[6]) - 1
|
||||
end
|
||||
if (step < 0 and field[5] > min) or (step > 0 and field[5] < max) then
|
||||
field[5] = field[5] + step
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
page = 1 + ((page + step - 1 + #pages) % #pages)
|
||||
edit = false
|
||||
current = 1
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
repeat
|
||||
current = 1 + ((current + step - 1 + #fields) % #fields)
|
||||
until fields[current][4]==1
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage(event)
|
||||
|
||||
for index = 1, 10, 1 do
|
||||
local field = fields[index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local attr = current == (index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
attr = attr + TEXT_COLOR
|
||||
|
||||
if field[4] == 1 then
|
||||
if field[3] == VALUE then
|
||||
lcd.drawNumber(field[1], field[2], field[5], LEFT + attr)
|
||||
elseif field[3] == COMBO then
|
||||
if field[5] >= 0 and field[5] < #(field[6]) then
|
||||
lcd.drawText(field[1],field[2], field[6][1+field[5]], attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[5]
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
if fields[current][5] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage(event)
|
||||
return 0
|
||||
end
|
||||
|
||||
-- set visibility flags starting with SECOND field of fields
|
||||
local function setFieldsVisible(...)
|
||||
local arg={...}
|
||||
local cnt = 2
|
||||
for i,v in ipairs(arg) do
|
||||
fields[cnt][4] = v
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- draws one letter mark
|
||||
local function drawMark(x, y, name)
|
||||
lcd.drawBitmap(ImgMarkBg, x, y)
|
||||
lcd.drawText(x+8, y+3, name, TEXT_COLOR)
|
||||
end
|
||||
|
||||
|
||||
local ThrottleFields = {
|
||||
{50, 50, COMBO, 1, 2, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local ThrottleBackground
|
||||
|
||||
local function runThrottleConfig(event)
|
||||
lcd.clear()
|
||||
if ThrottleBackground == nil then
|
||||
ThrottleBackground = Bitmap.open("img/throttle.png")
|
||||
end
|
||||
lcd.drawBitmap(ThrottleBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = ThrottleFields
|
||||
lcd.drawText(40, 20, "Assign Throttle channel", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local RollFields = {
|
||||
{50, 50, COMBO, 1, 0, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local RollBackground
|
||||
|
||||
local function runRollConfig(event)
|
||||
lcd.clear()
|
||||
if RollBackground == nil then
|
||||
RollBackground = Bitmap.open("img/roll.png")
|
||||
end
|
||||
lcd.drawBitmap(RollBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = RollFields
|
||||
lcd.drawText(40, 20, "Assign Roll channel", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local PitchFields = {
|
||||
{50, 50, COMBO, 1, 1, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local PitchBackground
|
||||
|
||||
local function runPitchConfig(event)
|
||||
lcd.clear()
|
||||
if PitchBackground == nil then
|
||||
PitchBackground = Bitmap.open("img/pitch.png")
|
||||
end
|
||||
lcd.drawBitmap(PitchBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = PitchFields
|
||||
lcd.drawText(40, 20, "Assign Pitch channel", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local YawFields = {
|
||||
{50, 50, COMBO, 1, 3, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local YawBackground
|
||||
|
||||
local function runYawConfig(event)
|
||||
lcd.clear()
|
||||
if YawBackground == nil then
|
||||
YawBackground = Bitmap.open("img/yaw.png")
|
||||
end
|
||||
lcd.drawBitmap(YawBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = YawFields
|
||||
lcd.drawText(40, 20, "Assign Yaw channel", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local ArmFields = {
|
||||
{50, 50, COMBO, 1, 5, { "SA", "SB", "SC", "SD", "SE", "SF"} },
|
||||
}
|
||||
|
||||
local ArmBackground
|
||||
|
||||
local function runArmConfig(event)
|
||||
lcd.clear()
|
||||
if ArmBackground == nil then
|
||||
ArmBackground = Bitmap.open("img/arm.png")
|
||||
end
|
||||
lcd.drawBitmap(ArmBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = ArmFields
|
||||
lcd.drawText(40, 20, "Assign Arm switch", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local BeeperFields = {
|
||||
{50, 50, COMBO, 1, 3, { "SA", "SB", "SC", "SD", "SE", "SF"} },
|
||||
}
|
||||
|
||||
local BeeperBackground
|
||||
|
||||
local function runBeeperConfig(event)
|
||||
lcd.clear()
|
||||
if BeeperBackground == nil then
|
||||
BeeperBackground = Bitmap.open("img/beeper.png")
|
||||
end
|
||||
lcd.drawBitmap(BeeperBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = BeeperFields
|
||||
lcd.drawText(40, 20, "Assign Beeper switch", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local ModeFields = {
|
||||
{50, 50, COMBO, 1, 0, { "SA", "SB", "SC", "SD", "SE", "SF"} },
|
||||
}
|
||||
|
||||
local ModeBackground
|
||||
|
||||
local function runModeConfig(event)
|
||||
lcd.clear()
|
||||
if ModeBackground == nil then
|
||||
ModeBackground = Bitmap.open("img/mode.png")
|
||||
end
|
||||
lcd.drawBitmap(ModeBackground, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = ModeFields
|
||||
lcd.drawText(40, 20, "Assign Mode switch", TEXT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 100, 30, TEXT_BGCOLOR)
|
||||
fields[1][4]=1
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local lineIndex
|
||||
local function drawNextChanelLine(text, text2)
|
||||
lcd.drawText(40, lineIndex, text, TEXT_COLOR)
|
||||
lcd.drawText(242, lineIndex, ": CH" .. text2 + 1, TEXT_COLOR)
|
||||
lineIndex = lineIndex + 20
|
||||
end
|
||||
|
||||
local function drawNextSwitchLine(text, text2)
|
||||
lcd.drawText(40, lineIndex, text, TEXT_COLOR)
|
||||
lcd.drawText(242, lineIndex, ": " ..switches[text2 + 1], TEXT_COLOR)
|
||||
lineIndex = lineIndex + 20
|
||||
end
|
||||
|
||||
|
||||
local ConfigSummaryFields = {
|
||||
{110, 250, COMBO, 1, 0, { "No, I need to change something", "Yes, all is well, create the model !"} },
|
||||
}
|
||||
|
||||
local ImgSummary
|
||||
|
||||
local function runConfigSummary(event)
|
||||
lcd.clear()
|
||||
if ImgSummary == nil then
|
||||
ImgSummary = Bitmap.open("img/summary.png")
|
||||
end
|
||||
fields = ConfigSummaryFields
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgSummary, 300, 60)
|
||||
lineIndex = 40
|
||||
-- throttle
|
||||
drawNextChanelLine("Throttle channel", ThrottleFields[1][5])
|
||||
-- roll
|
||||
drawNextChanelLine("Roll channel",RollFields[1][5])
|
||||
-- pitch
|
||||
drawNextChanelLine("Pitch channel",PitchFields[1][5])
|
||||
-- yaw
|
||||
drawNextChanelLine("Yaw channel",YawFields[1][5])
|
||||
-- arm
|
||||
drawNextSwitchLine("Arm switch",ArmFields[1][5])
|
||||
-- beeper
|
||||
drawNextSwitchLine("Beeper switch",BeeperFields[1][5])
|
||||
-- mode
|
||||
drawNextSwitchLine("Mode switch",ModeFields[1][5])
|
||||
|
||||
local result = runFieldsPage(event)
|
||||
if(fields[1][5] == 1 and edit == false) then
|
||||
selectPage(1)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function addMix(channel, input, name, weight, index)
|
||||
local mix = { source=input, name=name }
|
||||
if weight ~= nil then
|
||||
mix.weight = weight
|
||||
end
|
||||
if index == nil then
|
||||
index = 0
|
||||
end
|
||||
model.insertMix(channel, index, mix)
|
||||
end
|
||||
|
||||
local function createModel(event)
|
||||
lcd.clear()
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgSummary, 300, 60)
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
-- throttle
|
||||
addMix(ThrottleFields[1][5], MIXSRC_FIRST_INPUT+defaultChannel(2), "Thr")
|
||||
-- roll
|
||||
addMix(RollFields[1][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "Roll")
|
||||
-- pitch
|
||||
addMix(PitchFields[1][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "Pitch")
|
||||
-- yaw
|
||||
addMix(YawFields[1][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "Yaw")
|
||||
addMix(4, MIXSRC_SA + ArmFields[1][5], "Arm")
|
||||
addMix(5, MIXSRC_SA + BeeperFields[1][5], "Beeper")
|
||||
addMix(6, MIXSRC_SA + ModeFields[1][5], "Mode")
|
||||
|
||||
lcd.drawText(70, 90, "Model successfully created !", TEXT_COLOR)
|
||||
lcd.drawText(100, 130, "Press RTN to exit", TEXT_COLOR)
|
||||
return 2
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit = 1, false
|
||||
pages = {
|
||||
runThrottleConfig,
|
||||
runRollConfig,
|
||||
runPitchConfig,
|
||||
runYawConfig,
|
||||
runArmConfig,
|
||||
runBeeperConfig,
|
||||
runModeConfig,
|
||||
runConfigSummary,
|
||||
createModel,
|
||||
}
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE and page < #pages-1 then
|
||||
selectPage(1)
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE and page > 1 then
|
||||
killEvents(event);
|
||||
selectPage(-1)
|
||||
end
|
||||
|
||||
local result = pages[page](event)
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 506 B |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 10 KiB |
@@ -1,478 +0,0 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
local VALUE = 0
|
||||
local COMBO = 1
|
||||
|
||||
local edit = false
|
||||
local page = 1
|
||||
local current = 1
|
||||
local pages = {}
|
||||
local fields = {}
|
||||
|
||||
-- load common Bitmaps
|
||||
local ImgMarkBg = Bitmap.open("img/mark_bg.png")
|
||||
local BackgroundImg = Bitmap.open("img/background.png")
|
||||
local ImgPlane = Bitmap.open("img/plane.png")
|
||||
local ImgPageUp = Bitmap.open("img/pageup.png")
|
||||
local ImgPageDn = Bitmap.open("img/pagedn.png")
|
||||
|
||||
|
||||
-- Change display attribute to current field
|
||||
local function addField(step)
|
||||
local field = fields[current]
|
||||
local min, max
|
||||
if field[3] == VALUE then
|
||||
min = field[6]
|
||||
max = field[7]
|
||||
elseif field[3] == COMBO then
|
||||
min = 0
|
||||
max = #(field[6]) - 1
|
||||
end
|
||||
if (step < 0 and field[5] > min) or (step > 0 and field[5] < max) then
|
||||
field[5] = field[5] + step
|
||||
end
|
||||
end
|
||||
|
||||
-- Select the next or previous page
|
||||
local function selectPage(step)
|
||||
page = 1 + ((page + step - 1 + #pages) % #pages)
|
||||
edit = false
|
||||
current = 1
|
||||
end
|
||||
|
||||
-- Select the next or previous editable field
|
||||
local function selectField(step)
|
||||
repeat
|
||||
current = 1 + ((current + step - 1 + #fields) % #fields)
|
||||
until fields[current][4]==1
|
||||
end
|
||||
|
||||
-- Redraw the current page
|
||||
local function redrawFieldsPage(event)
|
||||
|
||||
for index = 1, 10, 1 do
|
||||
local field = fields[index]
|
||||
if field == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local attr = current == (index) and ((edit == true and BLINK or 0) + INVERS) or 0
|
||||
attr = attr + DEFAULT_COLOR
|
||||
|
||||
if field[4] == 1 then
|
||||
if field[3] == VALUE then
|
||||
lcd.drawNumber(field[1], field[2], field[5], LEFT + attr)
|
||||
elseif field[3] == COMBO then
|
||||
if field[5] >= 0 and field[5] < #(field[6]) then
|
||||
lcd.drawText(field[1],field[2], field[6][1+field[5]], attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateField(field)
|
||||
local value = field[5]
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function runFieldsPage(event)
|
||||
if event == EVT_VIRTUAL_EXIT then -- exit script
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_ENTER then -- toggle editing/selecting current field
|
||||
if fields[current][5] ~= nil then
|
||||
edit = not edit
|
||||
if edit == false then
|
||||
updateField(fields[current])
|
||||
end
|
||||
end
|
||||
elseif edit then
|
||||
if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
|
||||
addField(1)
|
||||
elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then
|
||||
addField(-1)
|
||||
end
|
||||
else
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
selectField(1)
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
selectField(-1)
|
||||
end
|
||||
end
|
||||
redrawFieldsPage(event)
|
||||
return 0
|
||||
end
|
||||
|
||||
-- set visibility flags starting with SECOND field of fields
|
||||
local function setFieldsVisible(...)
|
||||
local arg={...}
|
||||
local cnt = 2
|
||||
for i,v in ipairs(arg) do
|
||||
fields[cnt][4] = v
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- draws one letter mark
|
||||
local function drawMark(x, y, name)
|
||||
lcd.drawBitmap(ImgMarkBg, x, y)
|
||||
lcd.drawText(x+8, y+3, name, DEFAULT_COLOR)
|
||||
end
|
||||
|
||||
|
||||
local MotorFields = {
|
||||
{50, 50, COMBO, 1, 1, { "No", "Yes"} },
|
||||
{50, 127, COMBO, 1, 2, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local ImgEngine
|
||||
|
||||
local function runMotorConfig(event)
|
||||
lcd.clear()
|
||||
if ImgEngine == nil then
|
||||
ImgEngine = Bitmap.open("img/prop.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
lcd.drawBitmap(ImgEngine, 310, 50)
|
||||
fields = MotorFields
|
||||
lcd.drawText(40, 20, "Does your model have a motor ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 200, 30, TEXT_BGCOLOR)
|
||||
fields[2][4]=0
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawText(40, 100, "What channel is it on ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
fields[2][4]=1
|
||||
end
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
-- fields format : {[1]x, [2]y, [3]COMBO, [4]visible, [5]default, [6]{values}}
|
||||
-- fields format : {[1]x, [2]y, [3]VALUE, [4]visible, [5]default, [6]min, [7]max}
|
||||
local AilFields = {
|
||||
{50, 50, COMBO, 1, 2, { "None", "One, or two with Y cable", "Two"} },
|
||||
{50, 127, COMBO, 1, 0, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, -- Ail1 chan
|
||||
{50, 167, COMBO, 1, 4, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, -- Ail2 chan
|
||||
}
|
||||
|
||||
local ImgAilR
|
||||
local ImgAilL
|
||||
|
||||
local function runAilConfig(event)
|
||||
lcd.clear()
|
||||
if ImgAilR == nil then
|
||||
ImgAilR = Bitmap.open("img/rail.png")
|
||||
ImgAilL = Bitmap.open("img/lail.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
lcd.drawBitmap(ImgPlane, 252, 100)
|
||||
fields = AilFields
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawBitmap(ImgAilR, 324, 123)
|
||||
lcd.drawBitmap(ImgAilL, 275, 210)
|
||||
drawMark(362, 132, "A")
|
||||
drawMark(302, 227, "A")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
setFieldsVisible(1, 0)
|
||||
elseif fields[1][5] == 2 then
|
||||
lcd.drawBitmap(ImgAilR, 324, 123)
|
||||
lcd.drawBitmap(ImgAilL, 275, 210)
|
||||
drawMark(362, 132, "A")
|
||||
drawMark(302, 227, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1)
|
||||
else
|
||||
setFieldsVisible(0, 0)
|
||||
end
|
||||
lcd.drawText(40, 20, "Number of ailerons on your model ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local FlapsFields = {
|
||||
{50, 50, COMBO, 1, 0, { "No", "Yes, on one channel", "Yes, on two channels"} },
|
||||
{50, 127, COMBO, 1, 6, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
{50, 167, COMBO, 1, 7, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } },
|
||||
}
|
||||
|
||||
local ImgFlp
|
||||
|
||||
local function runFlapsConfig(event)
|
||||
lcd.clear()
|
||||
if ImgFlp == nil then
|
||||
ImgFlp = Bitmap.open("img/flap.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
lcd.drawBitmap(ImgPlane, 252, 100)
|
||||
fields = FlapsFields
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawBitmap(ImgFlp, 315, 143)
|
||||
lcd.drawBitmap(ImgFlp, 285, 191)
|
||||
drawMark(362, 132, "A")
|
||||
drawMark(302, 227, "A")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
setFieldsVisible(1, 0)
|
||||
elseif fields[1][5] == 2 then
|
||||
lcd.drawBitmap(ImgFlp, 315, 143)
|
||||
lcd.drawBitmap(ImgFlp, 285, 191)
|
||||
drawMark(362, 132, "A")
|
||||
drawMark(302, 227, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1)
|
||||
else
|
||||
setFieldsVisible(0, 0)
|
||||
end
|
||||
lcd.drawText(40, 20, "Does your model have flaps ?", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local TailFields = {
|
||||
{50, 50, COMBO, 1, 1, { "1 channel for Elevator, no Rudder", "One channel for Elevator, one for Rudder", "Two channels for Elevator, one for Rudder", "V Tail"} },
|
||||
{50, 127, COMBO, 1, 1, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, --ele
|
||||
{50, 167, COMBO, 1, 3, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, --rud
|
||||
{50, 207, COMBO, 0, 5, { "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8" } }, --ele2
|
||||
}
|
||||
|
||||
local ImgTail
|
||||
local ImgVTail
|
||||
local ImgTailRud
|
||||
|
||||
local function runTailConfig(event)
|
||||
lcd.clear()
|
||||
if ImgTail == nil then
|
||||
ImgTail = Bitmap.open("img/tail.png")
|
||||
ImgVTail = Bitmap.open("img/vtail.png")
|
||||
ImgTailRud = Bitmap.open("img/tailrud.png")
|
||||
end
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgPageDn, 455, 95)
|
||||
fields = TailFields
|
||||
if fields[1][5] == 0 then
|
||||
lcd.drawBitmap(ImgTail, 252, 100)
|
||||
drawMark(275, 120, "A")
|
||||
drawMark(390, 155, "A")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
setFieldsVisible(1, 0, 0)
|
||||
end
|
||||
if fields[1][5] == 1 then
|
||||
lcd.drawBitmap(ImgTail, 252, 100)
|
||||
lcd.drawBitmap(ImgTailRud, 340, 100)
|
||||
drawMark(275, 120, "A")
|
||||
drawMark(390, 155, "A")
|
||||
drawMark(370, 112, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1, 0)
|
||||
end
|
||||
if fields[1][5] == 2 then
|
||||
lcd.drawBitmap(ImgTail, 252, 100)
|
||||
lcd.drawBitmap(ImgTailRud, 340, 100)
|
||||
drawMark(275, 120, "A")
|
||||
drawMark(390, 155, "C")
|
||||
drawMark(370, 112, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
lcd.drawFilledRectangle(40, 202, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 204, "C")
|
||||
setFieldsVisible(1, 1, 1)
|
||||
end
|
||||
if fields[1][5] == 3 then
|
||||
lcd.drawBitmap(ImgVTail, 252, 100)
|
||||
drawMark(315, 110, "A")
|
||||
drawMark(382, 120, "B")
|
||||
lcd.drawFilledRectangle(40, 122, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 124, "A")
|
||||
lcd.drawFilledRectangle(40, 162, 100, 30, TEXT_BGCOLOR)
|
||||
drawMark(152, 164, "B")
|
||||
setFieldsVisible(1, 1, 0)
|
||||
end
|
||||
lcd.drawText(40, 20, "Pick the tail config of your model", DEFAULT_COLOR)
|
||||
lcd.drawFilledRectangle(40, 45, 400, 30, TEXT_BGCOLOR)
|
||||
local result = runFieldsPage(event)
|
||||
return result
|
||||
end
|
||||
|
||||
local lineIndex
|
||||
local function drawNextLine(text, text2)
|
||||
lcd.drawText(40, lineIndex, text, DEFAULT_COLOR)
|
||||
lcd.drawText(242, lineIndex, ": CH" .. text2 + 1, DEFAULT_COLOR)
|
||||
lineIndex = lineIndex + 20
|
||||
end
|
||||
|
||||
local ConfigSummaryFields = {
|
||||
{110, 250, COMBO, 1, 0, { "No, I need to change something", "Yes, all is well, create the plane !"} },
|
||||
}
|
||||
|
||||
local ImgSummary
|
||||
|
||||
local function runConfigSummary(event)
|
||||
lcd.clear()
|
||||
if ImgSummary == nil then
|
||||
ImgSummary = Bitmap.open("img/summary.png")
|
||||
end
|
||||
fields = ConfigSummaryFields
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgPageUp, 0, 95)
|
||||
lcd.drawBitmap(ImgSummary, 300, 60)
|
||||
lineIndex = 40
|
||||
-- motors
|
||||
if(MotorFields[1][5] == 1) then
|
||||
drawNextLine("Motor channel", MotorFields[2][5])
|
||||
end
|
||||
-- ail
|
||||
if(AilFields[1][5] == 1) then
|
||||
drawNextLine("Aileron channel",AilFields[2][5])
|
||||
elseif (AilFields[1][5] == 2) then
|
||||
drawNextLine("Aileron Right channel",AilFields[2][5])
|
||||
drawNextLine("Aileron Left channel",AilFields[3][5])
|
||||
end
|
||||
-- flaps
|
||||
if(FlapsFields[1][5] == 1) then
|
||||
drawNextLine("Flaps channel",FlapsFields[2][5])
|
||||
elseif (FlapsFields[1][5] == 2) then
|
||||
drawNextLine("Flaps Right channel",FlapsFields[2][5])
|
||||
drawNextLine("Flaps Left channel",FlapsFields[3][5])
|
||||
end
|
||||
-- tail
|
||||
if(TailFields[1][5] == 0) then
|
||||
drawNextLine("Elevator channel",TailFields[2][5])
|
||||
elseif (TailFields[1][5] == 1) then
|
||||
drawNextLine("Elevator channel",TailFields[2][5])
|
||||
drawNextLine("Rudder channel",TailFields[3][5])
|
||||
elseif (TailFields[1][5] == 2) then
|
||||
drawNextLine("Elevator Right channel",TailFields[2][5])
|
||||
drawNextLine("Rudder channel",TailFields[3][5])
|
||||
drawNextLine("Elevator Left channel",TailFields[4][5])
|
||||
elseif (TailFields[1][5] == 3) then
|
||||
drawNextLine("V-Tail Right", TailFields[2][5])
|
||||
drawNextLine("V-Tail Left", TailFields[3][5])
|
||||
end
|
||||
local result = runFieldsPage(event)
|
||||
if(fields[1][5] == 1 and edit == false) then
|
||||
selectPage(1)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function addMix(channel, input, name, weight, index)
|
||||
local mix = { source=input, name=name }
|
||||
if weight ~= nil then
|
||||
mix.weight = weight
|
||||
end
|
||||
if index == nil then
|
||||
index = 0
|
||||
end
|
||||
model.insertMix(channel, index, mix)
|
||||
end
|
||||
|
||||
local function createModel(event)
|
||||
lcd.clear()
|
||||
lcd.drawBitmap(BackgroundImg, 0, 0)
|
||||
lcd.drawBitmap(ImgSummary, 300, 60)
|
||||
model.defaultInputs()
|
||||
model.deleteMixes()
|
||||
-- motor
|
||||
if(MotorFields[1][5] == 1) then
|
||||
addMix(MotorFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(2), "Motor")
|
||||
end
|
||||
-- Ailerons
|
||||
if(AilFields[1][5] == 1) then
|
||||
addMix(AilFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "Ail")
|
||||
elseif (AilFields[1][5] == 2) then
|
||||
addMix(AilFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "AilR")
|
||||
addMix(AilFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(3), "AilL", -100)
|
||||
end
|
||||
-- Flaps
|
||||
if(FlapsFields[1][5] == 1) then
|
||||
addMix(FlapsFields[2][5], MIXSRC_SA, "Flaps")
|
||||
elseif (FlapsFields[1][5] == 2) then
|
||||
addMix(FlapsFields[2][5], MIXSRC_SA, "FlapsR")
|
||||
addMix(FlapsFields[3][5], MIXSRC_SA, "FlapsL")
|
||||
end
|
||||
-- Tail
|
||||
if(TailFields[1][5] == 0) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "Elev")
|
||||
elseif (TailFields[1][5] == 1) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "Elev")
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder")
|
||||
elseif (TailFields[1][5] == 2) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "ElevR")
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "Rudder")
|
||||
addMix(TailFields[4][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "ElevL")
|
||||
elseif (TailFields[1][5] == 3) then
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "V-EleR", 50)
|
||||
addMix(TailFields[2][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "V-RudR", 50, 1)
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(1), "V-EleL", 50)
|
||||
addMix(TailFields[3][5], MIXSRC_FIRST_INPUT+defaultChannel(0), "V-RudL", -50, 1)
|
||||
end
|
||||
lcd.drawText(70, 90, "Model successfully created !", DEFAULT_COLOR)
|
||||
lcd.drawText(100, 130, "Press RTN to exit", DEFAULT_COLOR)
|
||||
return 2
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function init()
|
||||
current, edit = 1, false
|
||||
pages = {
|
||||
runMotorConfig,
|
||||
runAilConfig,
|
||||
runFlapsConfig,
|
||||
runTailConfig,
|
||||
runConfigSummary,
|
||||
createModel,
|
||||
}
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE and page < #pages-1 then
|
||||
selectPage(1)
|
||||
elseif event == EVT_VIRTUAL_PREV_PAGE and page > 1 then
|
||||
killEvents(event);
|
||||
selectPage(-1)
|
||||
end
|
||||
|
||||
local result = pages[page](event)
|
||||
return result
|
||||
end
|
||||
|
||||
return { init=init, run=run }
|
||||
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 293 B |
|
Before Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 873 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 978 B |
|
Before Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 814 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 671 B |
|
Before Width: | Height: | Size: 796 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 980 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 604 B |