SD card is now in own repository at https://github.com/EdgeTX/edgetx-sdcard

Removing this obsolete copy here.
This commit is contained in:
rotorman
2021-07-31 17:04:52 +02:00
parent 4ec62d71b6
commit 94bb85142b
740 changed files with 0 additions and 22523 deletions
-1
View File
@@ -1 +0,0 @@
*/opentx.sdcard.version
-2
View File
@@ -1,2 +0,0 @@
You can put firmware for your modules or radio in this folder.
Files in this folder are NOT automaticaly applied.
-3
View File
@@ -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
View File
@@ -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 }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

@@ -1 +0,0 @@
Scripts that need to be available in TOOLS menu should be in this directory
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

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 }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

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 }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

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 }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

Some files were not shown because too many files have changed in this diff Show More