mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-13 18:27:55 +00:00
Compare commits
4 Commits
2d469d074e
...
58f6716035
Author | SHA1 | Date | |
---|---|---|---|
|
58f6716035 | ||
|
2b15de0f90 | ||
|
be91409df9 | ||
|
4d8e440965 |
@ -1,771 +0,0 @@
|
|||||||
local toolName = "TNS|DSM Forward Programming v0.2|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, EXIT, EXIT_DONE = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
|
||||||
local MENU, LIST_MENU_NOCHANGING, LIST_MENU1, LIST_MENU2, VALUE_NOCHANGING = 0x1C, 0x6C, 0x0C, 0x4C, 0x60
|
|
||||||
local Phase = RX_VERSION
|
|
||||||
local Waiting_RX = 0
|
|
||||||
local Text = {}
|
|
||||||
local RxName = {}
|
|
||||||
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="" }
|
|
||||||
|
|
||||||
-- used for debug
|
|
||||||
local rxAnswer = ""
|
|
||||||
local debugLine = 0
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------
|
|
||||||
local function GetDebugInfo(lineNr) -- used for debug
|
|
||||||
local i
|
|
||||||
|
|
||||||
debugLine = lineNr
|
|
||||||
rxAnswer = "RX:"
|
|
||||||
for i=10, 25 do
|
|
||||||
rxAnswer = rxAnswer.." "..string.format("%02X", multiBuffer(i))
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------
|
|
||||||
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 Get_RxName(index)
|
|
||||||
out = RxName[index]
|
|
||||||
if out == nil then -- unknown...
|
|
||||||
out = "Unknown_"..string.format("%X",index)
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
------------------------------------------------------------------------------------------------------------
|
|
||||||
local function DSM_Release()
|
|
||||||
multiBuffer( 0, 0 )
|
|
||||||
Phase = EXIT_DONE
|
|
||||||
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_EXIT then
|
|
||||||
if Phase == RX_VERSION then
|
|
||||||
DSM_Release()
|
|
||||||
else
|
|
||||||
Phase = EXIT
|
|
||||||
Waiting_RX = 0
|
|
||||||
end
|
|
||||||
elseif 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 and Line[i].Type ~= VALUE_NOCHANGING 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 and Line[i].Type ~= VALUE_NOCHANGING 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_LONG then
|
|
||||||
if Menu.EditLine ~= nil then
|
|
||||||
-- reset the value to default
|
|
||||||
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
|
|
||||||
Line[Menu.SelLine].Val = Line[Menu.SelLine].Def
|
|
||||||
Phase = VALUE_CHANGING
|
|
||||||
Waiting_RX = 0
|
|
||||||
end
|
|
||||||
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,Line[Menu.CurLine].Next) -- 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,Line[Menu.SelLine].Next,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,Line[Menu.SelLine].Next,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,Line[Menu.SelLine].Next) -- 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,Line[Menu.SelLine].Next)
|
|
||||||
|
|
||||||
elseif Phase == EXIT then
|
|
||||||
DSM_Send(0x1F,0x02,0xAA)
|
|
||||||
|
|
||||||
end
|
|
||||||
multiBuffer(10,0x00);
|
|
||||||
Retry = 50
|
|
||||||
-- -- -- -- -- -- -- -- -- -- -- -- receive part -- -- -- -- -- -- -- -- -- -- -- -- --
|
|
||||||
elseif multiBuffer(10) == 0x09 then
|
|
||||||
-- Answer received
|
|
||||||
-- GetDebugInfo(292) -- used for debug
|
|
||||||
|
|
||||||
--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_RxName(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, 0C new list type
|
|
||||||
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=>identifier of 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_MENU1 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 ~= MENU and line.Type ~= VALUE_NOCHANGING then -- updatable 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
|
|
||||||
-- Identify the line and update the value
|
|
||||||
for i = 0, 6 do
|
|
||||||
if Line[i] ~= nil and Line[i].Type ~= nil then
|
|
||||||
if Line[i].Type ~= MENU and Line[i].Next == multiBuffer(14) then -- identifier of line number stored in .Next
|
|
||||||
Line[i].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256)
|
|
||||||
Menu.CurLine = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
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) == 0xA7 then -- answer to EXIT command
|
|
||||||
DSM_Release()
|
|
||||||
|
|
||||||
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 == EXIT then
|
|
||||||
DSM_Release()
|
|
||||||
end
|
|
||||||
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
|
|
||||||
--lcd.drawText(10,55,debugLine.." "..rxAnswer) -- draw debug info
|
|
||||||
--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_MENU1 or Line[i].Type == LIST_MENU2 then
|
|
||||||
text = Get_Text(Line[i].Val+Line[i].Def)
|
|
||||||
elseif ( Line[i].Min == 0 and Line[i].Max == 100) or ( Line[i].Min == -100 and Line[i].Max == 100) or ( Line[i].Min == 0 and Line[i].Max == 150) or ( Line[i].Min == -150 and Line[i].Max == 150) then
|
|
||||||
text = Line[i].Val.." %"
|
|
||||||
else
|
|
||||||
--text = Line[i].Val .." T="..Line[i].Type -- used for debug
|
|
||||||
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') )
|
|
||||||
|
|
||||||
--RX names--
|
|
||||||
RxName[0x0001]="AR636B"
|
|
||||||
RxName[0x0014]="SPM4651T"
|
|
||||||
RxName[0x0015]="AR637T"
|
|
||||||
RxName[0x0016]="AR637TA"
|
|
||||||
RxName[0x0018]="FC6250HX"
|
|
||||||
RxName[0x001A]="AR8360T"
|
|
||||||
RxName[0x001E]="AR631"
|
|
||||||
|
|
||||||
--Text to be displayed -> need to use a file instead?
|
|
||||||
Text[0x0001]="Off"
|
|
||||||
Text[0x0002]="On"
|
|
||||||
Text[0x0003]="Inh"
|
|
||||||
Text[0x0004]="Act"
|
|
||||||
Text[0x000C]="Inhibit?" --?
|
|
||||||
Text[0x000D]="Gear"
|
|
||||||
|
|
||||||
--Lists--
|
|
||||||
Text[0x002E]="11ms"
|
|
||||||
Text[0x002F]="22ms"
|
|
||||||
Text[0x0032]="1 X"
|
|
||||||
Text[0x0033]="2 X"
|
|
||||||
Text[0x0034]="4 X"
|
|
||||||
Text[0x0035]="Inhibit?" --?
|
|
||||||
Text[0x0036]="Throttle"
|
|
||||||
Text[0x0037]="Aileron"
|
|
||||||
Text[0x0038]="Elevator"
|
|
||||||
Text[0x0039]="Rudder"
|
|
||||||
Text[0x003A]="Gear"
|
|
||||||
|
|
||||||
--******
|
|
||||||
--This part is strange since the AR637T needs
|
|
||||||
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
|
|
||||||
--But FOTO-PETE reports that it should be:
|
|
||||||
Text[0x0040]="Roll"
|
|
||||||
Text[0x0041]="Pitch"
|
|
||||||
Text[0x0042]="Yaw"
|
|
||||||
Text[0x0043]="Gain" -- FC6250HX
|
|
||||||
Text[0x0045]="Differential"
|
|
||||||
Text[0x0046]="Priority"
|
|
||||||
Text[0x0049]="Output Setup" -- FC6250HX
|
|
||||||
--******
|
|
||||||
|
|
||||||
Text[0x004A]="Failsafe"
|
|
||||||
Text[0x004B]="Main Menu"
|
|
||||||
Text[0x004E]="Position"
|
|
||||||
Text[0x0050]="Outputs"
|
|
||||||
Text[0x0051]="Output Channel 1"
|
|
||||||
Text[0x0052]="Output Channel 2"
|
|
||||||
Text[0x0053]="Output Channel 3"
|
|
||||||
Text[0x0054]="Output Channel 4"
|
|
||||||
Text[0x0055]="Output Channel 5"
|
|
||||||
Text[0x0056]="Output Channel 6"
|
|
||||||
--Text[0x005E]="Inhibit"
|
|
||||||
Text[0x005F]="Hold Last"
|
|
||||||
Text[0x0060]="Preset"
|
|
||||||
--Text[0x0061]="Custom"
|
|
||||||
--Messages--
|
|
||||||
Text[0x0071]="Proportional"
|
|
||||||
Text[0x0072]="Integral"
|
|
||||||
Text[0x0073]="Derivate"
|
|
||||||
Text[0x0078]="FM Channel"
|
|
||||||
Text[0x0080]="Orientation"
|
|
||||||
Text[0x0082]="Heading"
|
|
||||||
Text[0x0085]="Frame Rate"
|
|
||||||
Text[0x0086]="System Setup"
|
|
||||||
Text[0x0087]="F-Mode Setup"
|
|
||||||
Text[0x0088]="Enabled F-Modes"
|
|
||||||
Text[0x0089]="Gain Channel"
|
|
||||||
Text[0x008A]="Gain Sensitivity"
|
|
||||||
Text[0x008B]="Panic"
|
|
||||||
Text[0x008E]="Panic Delay"
|
|
||||||
Text[0x0090]="Apply"
|
|
||||||
Text[0x0092]="Start"
|
|
||||||
Text[0x0093]="Complete"
|
|
||||||
Text[0x0094]="Done"
|
|
||||||
Text[0x0097]="Factory Reset"
|
|
||||||
Text[0x0099]="Advanced Setup"
|
|
||||||
Text[0x009A]="Capture Failsafe Positions"
|
|
||||||
Text[0x009C]="Custom Failsafe"
|
|
||||||
Text[0x00A5]="First Time Setup"
|
|
||||||
Text[0x00AA]="Capture Gyro Gains"
|
|
||||||
Text[0x00AD]="Gain Channel Select"
|
|
||||||
Text[0x00B0]="Self-Level/Angle Dem"
|
|
||||||
Text[0x00B1]="Envelope"
|
|
||||||
Text[0x00B5]="Inhibit"
|
|
||||||
Text[0x00B6]="FM1"
|
|
||||||
Text[0x00B7]="FM2"
|
|
||||||
Text[0x00B8]="FM3"
|
|
||||||
Text[0x00B9]="FM4"
|
|
||||||
Text[0x00BA]="FM5"
|
|
||||||
Text[0x00BB]="FM6"
|
|
||||||
Text[0x00BC]="FM7"
|
|
||||||
Text[0x00BD]="FM8"
|
|
||||||
Text[0x00BE]="FM9"
|
|
||||||
Text[0x00BF]="FM10"
|
|
||||||
Text[0x00C7]="Calibrate Sensor"
|
|
||||||
Text[0x00CA]="SAFE/Panic Mode Setup"
|
|
||||||
Text[0x00D2]="Panic Channel"
|
|
||||||
Text[0x00D3]="Swashplate"
|
|
||||||
Text[0x00D5]="Agility"
|
|
||||||
Text[0x00D8]="Stop"
|
|
||||||
Text[0x00DA]="SAFE"
|
|
||||||
Text[0x00DB]="Stability"
|
|
||||||
Text[0x00DC]="@ per sec"
|
|
||||||
Text[0x00DD]="Tail rotor"
|
|
||||||
Text[0x00DE]="Setup"
|
|
||||||
Text[0x00DF]="AFR"
|
|
||||||
Text[0x00E0]="Collective"
|
|
||||||
Text[0x00E1]="Subtrim"
|
|
||||||
Text[0x00E2]="Phasing"
|
|
||||||
Text[0x00E4]="E-Ring"
|
|
||||||
Text[0x00E7]="Left"
|
|
||||||
Text[0x00E8]="Right"
|
|
||||||
Text[0x00F2]="Fixed"
|
|
||||||
Text[0x00F3]="Adjustable"
|
|
||||||
Text[0x00F9]="Gyro settings"
|
|
||||||
Text[0x00FE]="Stick Priority"
|
|
||||||
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[0x0106]="Any wing type, channel assignment,"
|
|
||||||
Text[0x0107]="subtrim, or servo reversing changes"
|
|
||||||
Text[0x0108]="require running through initial"
|
|
||||||
Text[0x0109]="setup again."
|
|
||||||
Text[0x0190]="Relearn Servo Settings"
|
|
||||||
Text[0x019C]="Enter Receiver Bind Mode"
|
|
||||||
Text[0x01D7]="SAFE Select Channel"
|
|
||||||
Text[0x01DC]="AS3X"
|
|
||||||
Text[0x01DD]="AS3X Settings"
|
|
||||||
Text[0x01DE]="AS3X Gains"
|
|
||||||
Text[0x01E0]="Rate Gains"
|
|
||||||
Text[0x01E2]="SAFE Settings"
|
|
||||||
Text[0x01E3]="SAFE Gains"
|
|
||||||
Text[0x01E6]="Attitude Trim"
|
|
||||||
Text[0x01E7]="Envelope"
|
|
||||||
Text[0x01E9]="Roll Right"
|
|
||||||
Text[0x01EA]="Roll Left"
|
|
||||||
Text[0x01EB]="Pitch Down"
|
|
||||||
Text[0x01EC]="Pitch Up"
|
|
||||||
Text[0x01EE]="Throttle to Pitch"
|
|
||||||
Text[0x01EF]="Low Thr to Pitch"
|
|
||||||
Text[0x01F0]="High Thr to Pitch"
|
|
||||||
Text[0x01F3]="Threshold"
|
|
||||||
Text[0x01F4]="Angle"
|
|
||||||
Text[0x01F6]="Failsafe Angles"
|
|
||||||
Text[0x01F8]="Safe Mode"
|
|
||||||
Text[0x01F9]="SAFE Select"
|
|
||||||
Text[0x01FC]="Panic Flight Mode"
|
|
||||||
Text[0x01FD]="SAFE Failsafe FMode"
|
|
||||||
Text[0x0208]="Decay"
|
|
||||||
Text[0x0209]="Save to Backup"
|
|
||||||
Text[0x020A]="Restore from Backup"
|
|
||||||
Text[0x020D]="First Time SAFE Setup"
|
|
||||||
Text[0x021A]="Set the model level,"
|
|
||||||
Text[0x021B]="and press Continue."
|
|
||||||
Text[0x021C]="" -- empty??
|
|
||||||
Text[0x021D]="" -- empty??
|
|
||||||
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[0x0226]="Angle Limits"
|
|
||||||
Text[0x0227]="Other settings"
|
|
||||||
Text[0x0229]="Set Orientation Manually"
|
|
||||||
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]="" -- empty??
|
|
||||||
Text[0x0231]="This will overwrite the"
|
|
||||||
Text[0x0232]="backup memory with your"
|
|
||||||
Text[0x0233]="current configuartion."
|
|
||||||
Text[0x0234]="" -- blank line
|
|
||||||
Text[0x0235]="" -- blank line
|
|
||||||
Text[0x0236]="This will overwrite the"
|
|
||||||
Text[0x0237]="current config with"
|
|
||||||
Text[0x0238]="that which is in"
|
|
||||||
Text[0x0239]="the backup memory."
|
|
||||||
Text[0x023A]="" -- blank line
|
|
||||||
Text[0x023D]="Copy Flight Mode Settings"
|
|
||||||
Text[0x0240]="Utilities"
|
|
||||||
Text[0x024C]="Gains will be captured on"
|
|
||||||
Text[0x024D]="Captured gains will be"
|
|
||||||
Text[0x024E]="Gains on"
|
|
||||||
Text[0x024F]="were captured and changed"
|
|
||||||
Text[0x0250]="from Adjustable to Fixed"
|
|
||||||
Text[0x0254]="Postive = Up, Negative = Down"
|
|
||||||
Text[0x0263]="Fixed/Adjustable Gains"
|
|
||||||
Text[0x0266]="Heading Gain"
|
|
||||||
Text[0x0267]="Positive = Nose Up/Roll Right"
|
|
||||||
Text[0x0268]="Negative = Nose Down/Roll Left"
|
|
||||||
Text[0x0269]="SAFE - Throttle to Pitch"
|
|
||||||
Text[0x026A]="Use CAUTION for Yaw gain!"
|
|
||||||
Text[0x8000]="FLIGHT MODE"
|
|
||||||
Text[0x8001]="Flight Mode 1"
|
|
||||||
Text[0x8002]="Flight Mode 2"
|
|
||||||
Text[0x8003]="Flight Mode 3"
|
|
||||||
end
|
|
||||||
------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Main
|
|
||||||
local function DSM_Run(event)
|
|
||||||
if event == nil then
|
|
||||||
error("Cannot be run as a model script!")
|
|
||||||
return 2
|
|
||||||
else
|
|
||||||
DSM_Menu(event)
|
|
||||||
DSM_Send_Receive()
|
|
||||||
DSM_Display()
|
|
||||||
end
|
|
||||||
if Phase == EXIT_DONE then
|
|
||||||
return 2
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return { init=DSM_Init, run=DSM_Run }
|
|
439
Lua_scripts/DSM FwdPrg_05_BW.lua
Normal file
439
Lua_scripts/DSM FwdPrg_05_BW.lua
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
local toolName = "TNS|DSM Forward Prog v0.5 (Text B&W) |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 SIMULATION_ON = true -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX
|
||||||
|
local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log)
|
||||||
|
local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
|
||||||
|
|
||||||
|
|
||||||
|
local dsmLib
|
||||||
|
if (SIMULATION_ON) then
|
||||||
|
-- library with SIMILATION VERSION. Works really well in Companion for GUI development
|
||||||
|
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON)
|
||||||
|
else
|
||||||
|
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
|
||||||
|
end
|
||||||
|
|
||||||
|
local PHASE = dsmLib.PHASE
|
||||||
|
local LINE_TYPE = dsmLib.LINE_TYPE
|
||||||
|
local DISP_ATTR = dsmLib.DISP_ATTR
|
||||||
|
|
||||||
|
local DSM_Context = dsmLib.DSM_Context
|
||||||
|
|
||||||
|
local LCD_W_USABLE = LCD_W-10
|
||||||
|
-- X for Menu Lines
|
||||||
|
local LCD_X_LINE_MENU = 10
|
||||||
|
-- X offsets for (Title: [Value] debugInfo) lines
|
||||||
|
local LCD_X_LINE_TITLE = 10
|
||||||
|
local LCD_X_LINE_VALUE = 230
|
||||||
|
local LCD_X_LINE_DEBUG = 390
|
||||||
|
|
||||||
|
-- Line Height: make it smaller debugging info tp LCD (some space buttom)
|
||||||
|
local LCD_Y_LINE_HEIGHT = (DEBUG_ON_LCD and 23) or 27 -- if DEBUG 23 else 27
|
||||||
|
-- Y offsets
|
||||||
|
local LCD_Y_MENU_TITLE = 20
|
||||||
|
-- Y offet
|
||||||
|
local LCD_Y_LINE_FIRST = LCD_Y_MENU_TITLE + 30
|
||||||
|
local LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_FIRST + 7 * LCD_Y_LINE_HEIGHT
|
||||||
|
|
||||||
|
local LCD_W_BUTTONS = 47
|
||||||
|
local LCD_H_BUTTONS = 25
|
||||||
|
local LCD_X_RIGHT_BUTTONS = LCD_W - LCD_W_BUTTONS - 5
|
||||||
|
|
||||||
|
local TEXT_SIZE = 0 -- NORMAL
|
||||||
|
|
||||||
|
local lastRefresh=0 -- Last time the screen was refreshed
|
||||||
|
local REFRESH_GUI_MS = 500/10 -- 500ms.. Screen Refresh Rate.. to not use unneded CPU time (in 10ms units to be compatible with getTime())
|
||||||
|
local originalValue = nil
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_SwitchSimulationOFF()
|
||||||
|
dsmLib.ReleaseConnection()
|
||||||
|
dsmLib.LOG_close()
|
||||||
|
|
||||||
|
SIMULATION_ON = false
|
||||||
|
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
|
||||||
|
DSM_Context = dsmLib.DSM_Context
|
||||||
|
|
||||||
|
dsmLib.Init(toolName) -- Initialize Library
|
||||||
|
dsmLib.StartConnection()
|
||||||
|
DSM_Context.Refresh_Display = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function openTx_lcd_sizeText(s)
|
||||||
|
return string.len(s)*5
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_Diplay_Button(x,y,w,h,text,selected)
|
||||||
|
local attr = (selected) and INVERS or 0 -- INVERS if line Selected
|
||||||
|
lcd.drawText(x+5,y+2, text, attr + TEXT_SIZE)
|
||||||
|
lcd.drawRectangle(x, y, w, h, LINE_COLOR)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_Display_Menu(menu)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local w= LCD_W_USABLE - LCD_W_BUTTONS - 10 -- usable Width for the Menu/Lines
|
||||||
|
|
||||||
|
-- Center Header
|
||||||
|
local tw = openTx_lcd_sizeText(menu.Text)
|
||||||
|
local x = w/2 - tw/2 -- Center of Screen - Center of Text
|
||||||
|
|
||||||
|
local bold = 0
|
||||||
|
if (TEXT_SIZE~=SMLSIZE) then -- Ignore Bold on small size screens
|
||||||
|
bold = BOLD
|
||||||
|
end
|
||||||
|
lcd.drawText(x,LCD_Y_MENU_TITLE,menu.Text,bold + TEXT_SIZE)
|
||||||
|
|
||||||
|
-- Back
|
||||||
|
if menu.BackId ~= 0 then
|
||||||
|
GUI_Diplay_Button(LCD_X_RIGHT_BUTTONS,LCD_Y_MENU_TITLE,LCD_W_BUTTONS,LCD_H_BUTTONS,"Back",ctx.SelLine == dsmLib.BACK_BUTTON)
|
||||||
|
end
|
||||||
|
-- Next ?
|
||||||
|
if menu.NextId ~= 0 then
|
||||||
|
GUI_Diplay_Button(LCD_X_RIGHT_BUTTONS,LCD_Y_LOWER_BUTTONS,LCD_W_BUTTONS,LCD_H_BUTTONS,"Next",ctx.SelLine == dsmLib.NEXT_BUTTON)
|
||||||
|
end
|
||||||
|
-- Prev?
|
||||||
|
if menu.PrevId ~= 0 then
|
||||||
|
GUI_Diplay_Button(0,LCD_Y_LOWER_BUTTONS,LCD_W_BUTTONS,LCD_H_BUTTONS,"Prev",ctx.SelLine == dsmLib.PREV_BUTTON)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug into LCD
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(0,LCD_Y_MENU_TITLE,dsmLib.phase2String(ctx.Phase),TEXT_SIZE + WARNING_COLOR) end -- Phase we are in
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_MENU,240,dsmLib.menu2String(menu),TEXT_SIZE + WARNING_COLOR) end -- Menu Info
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_Display_Line_Menu(x,y,w,h,line,selected)
|
||||||
|
local attr = (selected and INVERS) or 0 -- INVERS if line Selected
|
||||||
|
local bold = 0
|
||||||
|
local text = line.Text
|
||||||
|
|
||||||
|
if dsmLib.isSelectableLine(line) then
|
||||||
|
-- Menu Line
|
||||||
|
text = text .. " |>" --OPENTX
|
||||||
|
else -- SubHeaders and plain text lines
|
||||||
|
if (TEXT_SIZE~=SMLSIZE) then -- ignore bold on small size screens
|
||||||
|
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align???
|
||||||
|
local tw = openTx_lcd_sizeText(line.Text)+4
|
||||||
|
x = LCD_X_LINE_VALUE - tw -- Right
|
||||||
|
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Center??
|
||||||
|
local tw = openTx_lcd_sizeText(line.Text)
|
||||||
|
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_MENU)/2 - tw/2 -- Center - 1/2 Text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x,y, text, attr + bold + TEXT_SIZE)
|
||||||
|
|
||||||
|
end
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_Display_Line_Value(lineNum, line, value, selected, editing)
|
||||||
|
local bold = 0
|
||||||
|
|
||||||
|
local y = LCD_Y_LINE_FIRST+(LCD_Y_LINE_HEIGHT*lineNum)
|
||||||
|
local x = LCD_X_LINE_TITLE
|
||||||
|
|
||||||
|
---------- NAME Part
|
||||||
|
local header = line.Text
|
||||||
|
-- ONLY do this for Flight Mode (Right Align or Centered)
|
||||||
|
if (dsmLib.isFlightModeText(line.TextId)) then
|
||||||
|
-- Display Header + Value together
|
||||||
|
header = header .. " " .. value
|
||||||
|
|
||||||
|
-- Flight mode display attributes
|
||||||
|
if (TEXT_SIZE~=SMLSIZE) then -- ignore bold on small size screens
|
||||||
|
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align
|
||||||
|
local tw = openTx_lcd_sizeText(header)+4
|
||||||
|
x = LCD_X_LINE_VALUE - tw -- Right
|
||||||
|
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Centered
|
||||||
|
local tw = openTx_lcd_sizeText(header)
|
||||||
|
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_TITLE)/2 - tw/2 -- Center - 1/2 Text
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- No Flight Mode, no effects here
|
||||||
|
header = header .. ":"
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x, y, header, bold + TEXT_SIZE) -- display Line Header
|
||||||
|
|
||||||
|
--------- VALUE PART, Skip for Flight Mode since already show the value
|
||||||
|
if not dsmLib.isFlightModeText(line.TextId) then
|
||||||
|
local attrib = 0
|
||||||
|
value = value .. (line.Format or "") -- Append % if needed
|
||||||
|
|
||||||
|
if selected then
|
||||||
|
attrib = INVERS
|
||||||
|
if editing then -- blink editing entry
|
||||||
|
attrib = attrib + BLINK
|
||||||
|
value = "[ " .. value .. " ]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(LCD_X_LINE_VALUE,y, value, attrib + TEXT_SIZE) -- display value
|
||||||
|
end
|
||||||
|
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_DEBUG,y, line.MinMaxDebug or "", TEXT_SIZE + WARNING_COLOR) end -- display debug
|
||||||
|
end
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_Display()
|
||||||
|
local ctx = DSM_Context
|
||||||
|
lcd.clear()
|
||||||
|
|
||||||
|
local header = "DSM Fwrd Programming "
|
||||||
|
if ctx.Phase ~= PHASE.RX_VERSION then
|
||||||
|
header = header .. "RX "..ctx.RX.Name.." v"..ctx.RX.Version
|
||||||
|
end
|
||||||
|
|
||||||
|
--Draw title
|
||||||
|
if (TEXT_SIZE~=SMLSIZE) then -- ignore tool title small size screens
|
||||||
|
lcd.drawFilledRectangle(0, 0, LCD_W, 20, TITLE_BGCOLOR)
|
||||||
|
lcd.drawText(5, 0, header, MENU_TITLE_COLOR + TEXT_SIZE)
|
||||||
|
end
|
||||||
|
--Draw RX Menu
|
||||||
|
if ctx.Phase == PHASE.RX_VERSION then
|
||||||
|
lcd.drawText(LCD_X_LINE_TITLE,50,"No compatible DSM RX...", BLINK + TEXT_SIZE)
|
||||||
|
else
|
||||||
|
local menu = ctx.Menu
|
||||||
|
if menu.Text ~= nil then
|
||||||
|
|
||||||
|
GUI_Display_Menu(menu)
|
||||||
|
|
||||||
|
for i = 0, dsmLib.MAX_MENU_LINES do
|
||||||
|
local line = ctx.MenuLines[i]
|
||||||
|
|
||||||
|
if i == ctx.SelLine then
|
||||||
|
-- DEBUG: Display Selected Line info for ON SCREEN Debugging
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_TITLE,255,dsmLib.menuLine2String(line),TEXT_SIZE + WARNING_COLOR) end
|
||||||
|
end
|
||||||
|
|
||||||
|
if line ~= nil and line.Type ~= 0 then
|
||||||
|
if line.Type == LINE_TYPE.MENU then
|
||||||
|
-- Menu Line
|
||||||
|
GUI_Display_Line_Menu(LCD_X_LINE_MENU,LCD_Y_LINE_FIRST+(LCD_Y_LINE_HEIGHT*i), 350, LCD_Y_LINE_HEIGHT, line, i == ctx.SelLine)
|
||||||
|
else
|
||||||
|
-- list/value line
|
||||||
|
local value = line.Val
|
||||||
|
if line.Val ~= nil then
|
||||||
|
if dsmLib.isListLine(line) then -- for Lists of Strings, get the text
|
||||||
|
value = dsmLib.Get_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
|
||||||
|
local imgValue = dsmLib.Get_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display??
|
||||||
|
|
||||||
|
if (imgValue) then -- Optional Image for a Value
|
||||||
|
--TODO: Pending feature.. create images and put bitmap instead of a message
|
||||||
|
--Display the image/Alternate Text
|
||||||
|
lcd.drawText(LCD_X_LINE_TITLE, LCD_Y_LINE_FIRST+LCD_Y_LINE_HEIGHT, "Img:"..imgValue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
|
||||||
|
end
|
||||||
|
end -- if ~MENU
|
||||||
|
end -- if Line[i]~=nil
|
||||||
|
end -- for
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_RotEncVal(dir) -- return encoder speed to inc or dec values
|
||||||
|
local inc = 0
|
||||||
|
local Speed = getRotEncSpeed()
|
||||||
|
|
||||||
|
if Speed == ROTENC_MIDSPEED then
|
||||||
|
inc = (5 * dir)
|
||||||
|
elseif Speed == ROTENC_HIGHSPEED then
|
||||||
|
inc = (15 * dir)
|
||||||
|
else
|
||||||
|
inc = dir
|
||||||
|
end
|
||||||
|
|
||||||
|
return inc
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_HandleEvent(event, touchState)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local menu = ctx.Menu
|
||||||
|
local menuLines = ctx.MenuLines
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_EXIT then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_EXIT\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.Phase == PHASE.RX_VERSION then
|
||||||
|
dsmLib.ReleaseConnection()
|
||||||
|
else
|
||||||
|
if ctx.isEditing() then -- Editing a Line, need to restore original value
|
||||||
|
ctx.MenuLines[ctx.EditLine].Val = originalValue
|
||||||
|
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Update+Validate value in RX
|
||||||
|
ctx.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
|
||||||
|
else
|
||||||
|
dsmLib.ChangePhase(PHASE.EXIT)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_NEXT then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_NEXT\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.isEditing() then -- Editing a Line, need to inc the value
|
||||||
|
local line=ctx.MenuLines[ctx.EditLine]
|
||||||
|
dsmLib.Value_Add(line, GUI_RotEncVal(1))
|
||||||
|
else -- not editing, move selected line to NEXT
|
||||||
|
dsmLib.MoveSelectionLine(1)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_PREV then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_PREV\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.isEditing() then -- Editiing a line, need to dec the value
|
||||||
|
local line=ctx.MenuLines[ctx.EditLine]
|
||||||
|
dsmLib.Value_Add(line, GUI_RotEncVal(-1))
|
||||||
|
else -- not editing, move selected line to PREV
|
||||||
|
dsmLib.MoveSelectionLine(-1)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_ENTER_LONG then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.isEditing() then
|
||||||
|
-- reset the value to default
|
||||||
|
dsmLib.Value_Default( menuLines[ctx.EditLine]) -- Update RX value as needed
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_ENTER then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.SelLine == dsmLib.BACK_BUTTON then -- Back
|
||||||
|
dsmLib.GotoMenu(menu.BackId)
|
||||||
|
elseif ctx.SelLine == dsmLib.NEXT_BUTTON then -- Next
|
||||||
|
dsmLib.GotoMenu(menu.NextId)
|
||||||
|
elseif ctx.SelLine == dsmLib.PREV_BUTTON then -- Prev
|
||||||
|
dsmLib.GotoMenu(menu.PrevId)
|
||||||
|
elseif menuLines[ctx.SelLine].ValId ~= 0 then
|
||||||
|
if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Next menu exist
|
||||||
|
if (SIMULATION_ON and menuLines[ctx.SelLine].ValId==0xFFFF) then
|
||||||
|
-- SPECIAL Simulation menu to Exit Simulation and
|
||||||
|
-- comunicate with Real RX
|
||||||
|
GUI_SwitchSimulationOFF()
|
||||||
|
else
|
||||||
|
dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId) -- ValId is the MenuId to navigate to
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Editing a Line????
|
||||||
|
if ctx.isEditing() then
|
||||||
|
-- Change the Value and exit edit
|
||||||
|
ctx.EditLine = nil
|
||||||
|
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END)
|
||||||
|
else
|
||||||
|
-- enter Edit the current line
|
||||||
|
ctx.EditLine = ctx.SelLine
|
||||||
|
originalValue = menuLines[ctx.SelLine].Val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function init_screen_pos()
|
||||||
|
if LCD_W == 480 then -- TX16
|
||||||
|
-- use defaults in the script header
|
||||||
|
elseif LCD_W == 128 then --TX12 (128x64) -- Still needs some work on the vertical
|
||||||
|
DEBUG_ON_LCD = false -- no space for this
|
||||||
|
TEXT_SIZE = SMLSIZE
|
||||||
|
LCD_W_USABLE = 128
|
||||||
|
|
||||||
|
LCD_W_BUTTONS = 30
|
||||||
|
LCD_H_BUTTONS = 17
|
||||||
|
LCD_X_RIGHT_BUTTONS = 128 - LCD_W_BUTTONS - 5
|
||||||
|
|
||||||
|
LCD_X_LINE_MENU = 0
|
||||||
|
-- X offsets for (Title: [Value] debugInfo) lines
|
||||||
|
LCD_X_LINE_TITLE = 0
|
||||||
|
LCD_X_LINE_VALUE = 90
|
||||||
|
LCD_X_LINE_DEBUG = 110
|
||||||
|
|
||||||
|
LCD_Y_LINE_HEIGHT = 17
|
||||||
|
LCD_Y_MENU_TITLE = 0
|
||||||
|
LCD_Y_LINE_FIRST = LCD_Y_MENU_TITLE + 17
|
||||||
|
LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_FIRST + 7 * LCD_Y_LINE_HEIGHT
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Init
|
||||||
|
local function DSM_Init()
|
||||||
|
init_screen_pos()
|
||||||
|
dsmLib.Init(toolName) -- Initialize Library
|
||||||
|
return dsmLib.StartConnection()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Main
|
||||||
|
|
||||||
|
|
||||||
|
local function DSM_Run(event)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
|
||||||
|
if event == nil then
|
||||||
|
error("Cannot be run as a model script!")
|
||||||
|
dsmLib.LOG_close()
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
|
||||||
|
GUI_HandleEvent(event)
|
||||||
|
|
||||||
|
dsmLib.Send_Receive() -- Handle Send and Receive DSM Forward Programming Messages
|
||||||
|
|
||||||
|
local refreshInterval = REFRESH_GUI_MS
|
||||||
|
-- When using LCD BLINK attribute, we need faster refresh for BLINK to SHOW on LCD
|
||||||
|
if (ctx.EditLine or (ctx.Phase == PHASE.RX_VERSION)) then -- Editing or Requesting RX Version?
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
refreshInterval = 20 -- 200ms
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Refresh display only if needed and no faster than 500ms, utilize more CPU to speedup DSM communications
|
||||||
|
if (ctx.Refresh_Display and (getTime()-lastRefresh) > refreshInterval) then --300ms from last refresh
|
||||||
|
GUI_Display()
|
||||||
|
ctx.Refresh_Display=false
|
||||||
|
lastRefresh=getTime()
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctx.Phase == PHASE.EXIT_DONE then
|
||||||
|
dsmLib.LOG_close()
|
||||||
|
return 2
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return { init=DSM_Init, run=DSM_Run }
|
627
Lua_scripts/DSM FwdPrg_05_Color.lua
Normal file
627
Lua_scripts/DSM FwdPrg_05_Color.lua
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
local toolName = "TNS|DSM Forward Prog v0.5 (Color+Touch) |TNE"
|
||||||
|
local VERSION = "v0.5"
|
||||||
|
|
||||||
|
---- #########################################################################
|
||||||
|
---- # #
|
||||||
|
---- # 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 SIMULATION_ON = true -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX
|
||||||
|
local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log)
|
||||||
|
local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
|
||||||
|
local USE_SPECKTRUM_COLORS = true -- true: Use spectrum colors, false: use theme colors (default on OpenTX)
|
||||||
|
|
||||||
|
local dsmLib
|
||||||
|
if (SIMULATION_ON) then
|
||||||
|
-- library with SIMILATION VERSION. Works really well in Companion for GUI development
|
||||||
|
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON)
|
||||||
|
else
|
||||||
|
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
|
||||||
|
end
|
||||||
|
|
||||||
|
local PHASE = dsmLib.PHASE
|
||||||
|
local LINE_TYPE = dsmLib.LINE_TYPE
|
||||||
|
local DISP_ATTR = dsmLib.DISP_ATTR
|
||||||
|
local DSM_Context = dsmLib.DSM_Context
|
||||||
|
|
||||||
|
|
||||||
|
local lastRefresh=0 -- Last time the screen was refreshed
|
||||||
|
local REFRESH_GUI_MS = 300/10 -- 300ms.. Screen Refresh Rate.. to not waste CPU time (in 10ms units to be compatible with getTime())
|
||||||
|
local originalValue = nil
|
||||||
|
|
||||||
|
local touchButtonArea = {}
|
||||||
|
local EDIT_BUTTON = { DEFAULT=1001, DEC_10=1002, DEC_1=1003, INC_1=1004, INC_10=5, OK=1006, ESC=1007 }
|
||||||
|
|
||||||
|
local IS_EDGETX = false -- DEFAULT until Init changed it
|
||||||
|
|
||||||
|
local LCD_Y_MENU_TITLE = 20
|
||||||
|
local LCD_W_MENU_TITLE = LCD_W-100
|
||||||
|
|
||||||
|
local LCD_X_LINE_MENU = 30
|
||||||
|
local LCD_W_LINE_MENU = 350
|
||||||
|
|
||||||
|
local LCD_X_LINE_TITLE = 30
|
||||||
|
local LCD_X_LINE_VALUE = 230
|
||||||
|
local LCD_X_LINE_DEBUG = 390
|
||||||
|
|
||||||
|
|
||||||
|
local LCD_Y_LINE_START = LCD_Y_MENU_TITLE + 30
|
||||||
|
local LCD_Y_LINE_HEIGHT = (DEBUG_ON_LCD and 23) or 27 -- if DEBUG 23 else 27
|
||||||
|
|
||||||
|
local LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_START + 3 + (7 * LCD_Y_LINE_HEIGHT)
|
||||||
|
|
||||||
|
|
||||||
|
-- TOOL HEADER
|
||||||
|
local LCD_TOOL_HDR_COLOR = MENU_TITLE_COLOR
|
||||||
|
local LCD_TOOL_HDR_BGCOLOR = TITLE_BGCOLOR
|
||||||
|
-- MENU HEADER
|
||||||
|
local LCD_MENU_COLOR = MENU_TITLE_COLOR
|
||||||
|
local LCD_MENU_BGCOLOR = MENU_TITLE_BGCOLOR
|
||||||
|
-- LINE SELECTED
|
||||||
|
local LCD_SELECTED_COLOR = TEXT_INVERTED_COLOR
|
||||||
|
local LCD_SELECTED_BGCOLOR = TEXT_INVERTED_BGCOLOR
|
||||||
|
local LCD_EDIT_BGCOLOR = WARNING_COLOR
|
||||||
|
-- NORMAL TEXT
|
||||||
|
local LCD_NORMAL_COLOR = TEXT_COLOR
|
||||||
|
local LCD_DISABLE_COLOR = TEXT_DISABLE_COLOR
|
||||||
|
local LCD_DEBUG_COLOR = LINE_COLOR
|
||||||
|
-- NORMAL BOX FRAME COLOR
|
||||||
|
local LCD_BOX_COLOR = TEXT_DISABLE_COLOR
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------------- lcd.sizeText replacement -------------------------------------------------
|
||||||
|
-- EdgeTx dont have lcd.sizeText, so we do an equivalent one using the string length and 5px per character
|
||||||
|
local function my_lcd_sizeText(s)
|
||||||
|
print(string.format("EdgeTX=%s",IS_EDGETX))
|
||||||
|
-- return: If IS_EDGETX then lcd.sizeText() else string.len()
|
||||||
|
return (IS_EDGETX and lcd.sizeText(s)) or (string.len(s)*10)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function GUI_SwitchSimulationOFF()
|
||||||
|
dsmLib.ReleaseConnection()
|
||||||
|
dsmLib.LOG_close()
|
||||||
|
|
||||||
|
SIMULATION_ON = false
|
||||||
|
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
|
||||||
|
DSM_Context = dsmLib.DSM_Context
|
||||||
|
|
||||||
|
dsmLib.Init(toolName) -- Initialize Library
|
||||||
|
dsmLib.StartConnection()
|
||||||
|
DSM_Context.Refresh_Display = true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--------------------- Toucch Button Helpers ------------------------------------------------------------
|
||||||
|
local function GUI_addTouchButton(x,y,w,h,line)
|
||||||
|
-- Add new button info to end of the array
|
||||||
|
touchButtonArea[#touchButtonArea+1] = {x=x, y=y, w=w, h=h, line=line}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_getTouchButton(x,y)
|
||||||
|
for i = 1, #touchButtonArea do
|
||||||
|
local button = touchButtonArea[i]
|
||||||
|
-- is the coordinate inside the button area??
|
||||||
|
if (x >= button.x and x <= (button.x+button.w) and y >= button.y and (y <= button.y+button.h)) then
|
||||||
|
return button.line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_clearTouchButtons()
|
||||||
|
touchButtonArea = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
---------- Return Color to display Menu Lines ----------------------------------------------------------------
|
||||||
|
local function GUI_GetTextColor(lineNum)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local txtColor = LCD_NORMAL_COLOR
|
||||||
|
-- Gray Out any other line except the one been edited
|
||||||
|
if (ctx.isEditing() and ctx.EditLine~=lineNum) then txtColor=LCD_DISABLE_COLOR end
|
||||||
|
return txtColor
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_GetFrameColor(lineNum) -- Frame Color for Value/Menu Boxes
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local txtColor = LCD_BOX_COLOR
|
||||||
|
-- Gray Out any other line except the one been edited
|
||||||
|
if (ctx.EditLine~=lineNum) then txtColor=LCD_DISABLE_COLOR end
|
||||||
|
return txtColor
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------------------------------
|
||||||
|
-- Display Text inside a Rectangle. Inv: true means solid rectangle, false=only perimeter
|
||||||
|
local function GUI_Display_Boxed_Text(lineNum,x,y,w,h,text,inv)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local txtColor = GUI_GetTextColor(lineNum)
|
||||||
|
local frameColor = GUI_GetFrameColor(lineNum)
|
||||||
|
-- If editing this lineNum, chose EDIT Color, else SELECTED Color
|
||||||
|
local selectedBGColor = (ctx.EditLine==lineNum and LCD_EDIT_BGCOLOR) or LCD_SELECTED_BGCOLOR
|
||||||
|
|
||||||
|
if (inv) then
|
||||||
|
txtColor = LCD_SELECTED_COLOR
|
||||||
|
lcd.drawFilledRectangle(x-5, y-2, w, h, selectedBGColor)
|
||||||
|
else
|
||||||
|
lcd.drawRectangle(x-5, y-2, w, h, frameColor)
|
||||||
|
end
|
||||||
|
lcd.drawText(x , y, text, txtColor)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
------ Display Pre/Next/Back buttons
|
||||||
|
local function GUI_Diplay_Button(x,y,w,h,text,selected)
|
||||||
|
GUI_Display_Boxed_Text(-1,x,y,w,h,text,selected)
|
||||||
|
end
|
||||||
|
|
||||||
|
------ Display MENU type of lines (Navigation, SubHeaders, and plain text comments)
|
||||||
|
local function GUI_Display_Line_Menu(lineNum,line,selected)
|
||||||
|
-- Menu Lines can be navidation to other Menus (if Selectable)
|
||||||
|
-- Or SubHeaders or Messages
|
||||||
|
|
||||||
|
local txtColor = GUI_GetTextColor(lineNum)
|
||||||
|
local y = LCD_Y_LINE_START+(LCD_Y_LINE_HEIGHT*lineNum)
|
||||||
|
local x = LCD_X_LINE_MENU
|
||||||
|
|
||||||
|
if dsmLib.isSelectableLine(line) then -- Draw Selectable Menus in Boxes
|
||||||
|
GUI_Display_Boxed_Text(lineNum,x, y, LCD_W_LINE_MENU, LCD_Y_LINE_HEIGHT, line.Text,selected)
|
||||||
|
GUI_addTouchButton(x, y, LCD_W_LINE_MENU, LCD_Y_LINE_HEIGHT,lineNum)
|
||||||
|
else
|
||||||
|
-- Non Selectable Menu Lines, plain text
|
||||||
|
-- Can be use for sub headers or just regular text lines (like warnings)
|
||||||
|
|
||||||
|
local bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
|
||||||
|
|
||||||
|
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align???
|
||||||
|
local tw = my_lcd_sizeText(line.Text)+4
|
||||||
|
x = LCD_X_LINE_VALUE - tw -- Right
|
||||||
|
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Center??
|
||||||
|
local tw = my_lcd_sizeText(line.Text)
|
||||||
|
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_MENU)/2 - tw/2 -- Center - 1/2 Text
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x, y, line.Text, txtColor + bold)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
------ Display NAME : VALUES type of lines
|
||||||
|
local function GUI_Display_Line_Value(lineNum, line, value, selected, editing)
|
||||||
|
-- This Displays Name and Value Pairs
|
||||||
|
local txtColor = GUI_GetTextColor(lineNum)
|
||||||
|
local bold = 0
|
||||||
|
local y = LCD_Y_LINE_START+(LCD_Y_LINE_HEIGHT*lineNum)
|
||||||
|
local x = LCD_X_LINE_TITLE
|
||||||
|
|
||||||
|
--if (editing) then -- Any Special color/effect when editing??
|
||||||
|
-- value = "["..value .. "]"
|
||||||
|
--end
|
||||||
|
|
||||||
|
---------- NAME Part
|
||||||
|
local header = line.Text
|
||||||
|
-- ONLY do this for Flight Mode (Right Align or Centered)
|
||||||
|
if (dsmLib.isFlightModeText(line.TextId)) then
|
||||||
|
-- Display Header + Value together
|
||||||
|
header = header .. " " .. value
|
||||||
|
|
||||||
|
-- Bold Text???
|
||||||
|
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
|
||||||
|
|
||||||
|
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align
|
||||||
|
local tw = my_lcd_sizeText(header)+4
|
||||||
|
x = LCD_X_LINE_VALUE - tw -- Right
|
||||||
|
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Centered
|
||||||
|
local tw = my_lcd_sizeText(header)
|
||||||
|
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_TITLE)/2 - tw/2 -- Center - 1/2 Text
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- No Flight Mode, no effects here
|
||||||
|
header = header .. ":"
|
||||||
|
end
|
||||||
|
|
||||||
|
lcd.drawText(x, y, header, txtColor + bold) -- display Line Header
|
||||||
|
|
||||||
|
--------- VALUE PART, Skip for Flight Mode since already show the value
|
||||||
|
if not dsmLib.isFlightModeText(line.TextId) then
|
||||||
|
value = value .. (line.Format or "") -- Append % if needed
|
||||||
|
|
||||||
|
if dsmLib.isSelectableLine(line) then
|
||||||
|
-- Can select/edit value, Box it
|
||||||
|
local tw = my_lcd_sizeText(value)+10 -- Width of the Text in the lcd
|
||||||
|
GUI_Display_Boxed_Text(lineNum,LCD_X_LINE_VALUE,y,tw,LCD_Y_LINE_HEIGHT,value,selected)
|
||||||
|
GUI_addTouchButton(LCD_X_LINE_VALUE,y,tw,LCD_Y_LINE_HEIGHT,lineNum)
|
||||||
|
else -- Not Editable, Plain Text
|
||||||
|
lcd.drawText(LCD_X_LINE_VALUE, y, value, txtColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug info for line Value RANGE when Debug on LCD
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_DEBUG, y, line.MinMaxDebug or "", SMLSIZE + LCD_DEBUG_COLOR) end -- display debug Min/Max
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GUI_Display_Menu(menu)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local w= LCD_W_MENU_TITLE
|
||||||
|
|
||||||
|
-- Center Header
|
||||||
|
local tw = my_lcd_sizeText(menu.Text)
|
||||||
|
local x = w/2 - tw/2 -- Center of Screen - Center of Text
|
||||||
|
|
||||||
|
lcd.drawFilledRectangle(0, LCD_Y_MENU_TITLE-2, w, LCD_Y_LINE_HEIGHT-2, LCD_MENU_BGCOLOR)
|
||||||
|
lcd.drawText(x,LCD_Y_MENU_TITLE,menu.Text, LCD_MENU_COLOR + BOLD)
|
||||||
|
|
||||||
|
-- Back Button
|
||||||
|
if menu.BackId ~= 0 then
|
||||||
|
GUI_Diplay_Button(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,"Back",ctx.SelLine == dsmLib.BACK_BUTTON)
|
||||||
|
GUI_addTouchButton(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,dsmLib.BACK_BUTTON)
|
||||||
|
end
|
||||||
|
-- Next Button
|
||||||
|
if menu.NextId ~= 0 then
|
||||||
|
GUI_Diplay_Button(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,"Next",ctx.SelLine == dsmLib.NEXT_BUTTON)
|
||||||
|
GUI_addTouchButton(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,dsmLib.NEXT_BUTTON)
|
||||||
|
end
|
||||||
|
-- Prev Button
|
||||||
|
if menu.PrevId ~= 0 then
|
||||||
|
GUI_Diplay_Button(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,"Prev",ctx.SelLine == dsmLib.PREV_BUTTON)
|
||||||
|
GUI_addTouchButton(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,dsmLib.PREV_BUTTON)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug on LCD, Show the menu Indo and Phase we are on
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(0,LCD_Y_MENU_TITLE,dsmLib.phase2String(ctx.Phase),SMLSIZE+LCD_DEBUG_COLOR) end -- Phase we are in
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(0,240,dsmLib.menu2String(menu),SMLSIZE+LCD_DEBUG_COLOR) end -- Menu Info
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Display the EDIT mode buttons when editing a value
|
||||||
|
|
||||||
|
local function GUI_Display_Edit_Buttons(line)
|
||||||
|
GUI_clearTouchButtons() -- Only this buttons can be touched
|
||||||
|
local x = 15 -- Inittial X position
|
||||||
|
local w = 55 -- Width of the buttons
|
||||||
|
|
||||||
|
local showPrev = line.Val > line.Min
|
||||||
|
local showNext = line.Val < line.Max
|
||||||
|
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,"ESC",true)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.ESC)
|
||||||
|
|
||||||
|
x=x+w+10
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," Def",true)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEFAULT)
|
||||||
|
|
||||||
|
x=x+w+10
|
||||||
|
if (not dsmLib.isListLine(line)) then
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," << ",showPrev)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEC_10)
|
||||||
|
end
|
||||||
|
|
||||||
|
x=x+w+10
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," <",showPrev)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEC_1)
|
||||||
|
|
||||||
|
x=x+w+10
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," >",showNext)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.INC_1)
|
||||||
|
|
||||||
|
x=x+w+10
|
||||||
|
if (not dsmLib.isListLine(line)) then
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," >>",showNext)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.INC_10)
|
||||||
|
end
|
||||||
|
|
||||||
|
x=x+w+10
|
||||||
|
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," OK",true)
|
||||||
|
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.OK)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_Display()
|
||||||
|
local ctx = DSM_Context
|
||||||
|
lcd.clear()
|
||||||
|
GUI_clearTouchButtons()
|
||||||
|
|
||||||
|
if LCD_W == 480 then
|
||||||
|
local header = "DSM Forward Programming "..VERSION.." "
|
||||||
|
if ctx.Phase ~= PHASE.RX_VERSION then
|
||||||
|
header = header .. "RX "..ctx.RX.Name.." v"..ctx.RX.Version
|
||||||
|
end
|
||||||
|
|
||||||
|
--Draw title
|
||||||
|
lcd.drawFilledRectangle(0, 0, LCD_W, 17, LCD_TOOL_HDR_BGCOLOR)
|
||||||
|
lcd.drawText(5, 0, header, LCD_TOOL_HDR_COLOR + SMLSIZE)
|
||||||
|
--Draw RX Menu
|
||||||
|
if ctx.Phase == PHASE.RX_VERSION then
|
||||||
|
lcd.drawText(LCD_X_LINE_TITLE,100,"No compatible DSM RX...", BLINK)
|
||||||
|
else
|
||||||
|
local menu = ctx.Menu
|
||||||
|
|
||||||
|
|
||||||
|
if menu.Text ~= nil then
|
||||||
|
GUI_Display_Menu(menu)
|
||||||
|
|
||||||
|
for i = 0, dsmLib.MAX_MENU_LINES do
|
||||||
|
local line = ctx.MenuLines[i]
|
||||||
|
|
||||||
|
if i == ctx.SelLine then
|
||||||
|
-- DEBUG: Display Selected Line info for ON SCREEN Debugging
|
||||||
|
if (DEBUG_ON_LCD) then lcd.drawText(0,255,dsmLib.menuLine2String(line),SMLSIZE + LCD_DEBUG_COLOR) end
|
||||||
|
end
|
||||||
|
|
||||||
|
if line ~= nil and line.Type ~= 0 then
|
||||||
|
if line.Type == LINE_TYPE.MENU then
|
||||||
|
GUI_Display_Line_Menu(i, line, i == ctx.SelLine)
|
||||||
|
else
|
||||||
|
-- list/value line
|
||||||
|
local value, imgValue = line.Val, nil
|
||||||
|
|
||||||
|
if line.Val ~= nil then
|
||||||
|
if dsmLib.isListLine(line) then -- for Lists of Strings, get the text
|
||||||
|
value = dsmLib.Get_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
|
||||||
|
imgValue = dsmLib.Get_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display??
|
||||||
|
|
||||||
|
if (imgValue) then -- Optional Image for a Value
|
||||||
|
--TODO: Pending feature.. create images and put bitmap instead of a message
|
||||||
|
--Display the image/Alternate Text
|
||||||
|
lcd.drawText(LCD_X_LINE_TITLE, LCD_Y_LINE_START+LCD_Y_LINE_HEIGHT, "Img:"..imgValue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
|
||||||
|
end
|
||||||
|
end -- if ~MENU
|
||||||
|
end -- if Line[i]~=nil
|
||||||
|
end -- for
|
||||||
|
|
||||||
|
if IS_EDGETX and ctx.isEditing() then
|
||||||
|
GUI_Display_Edit_Buttons(ctx.MenuLines[ctx.EditLine])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Different Resolution.. Maybe just adjusting some of the constants will work, adjust it in DSM_Init??
|
||||||
|
-- LCD_X_LINE_TITLE, LCD_Y_LINE_START, etc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
local function GUI_RotEncVal(dir) -- return encoder speed to inc or dec values
|
||||||
|
local inc = 0
|
||||||
|
local Speed = getRotEncSpeed()
|
||||||
|
|
||||||
|
if Speed == ROTENC_MIDSPEED then inc = (5 * dir)
|
||||||
|
elseif Speed == ROTENC_HIGHSPEED then inc = (15 * dir)
|
||||||
|
else inc = dir end
|
||||||
|
|
||||||
|
return inc
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
-- Translate Tap/Touch of EDIT buttons to equivalent Key events
|
||||||
|
local function GUI_Translate_Edit_Buttons(button)
|
||||||
|
local event = EVT_TOUCH_TAP
|
||||||
|
local editInc = nil
|
||||||
|
|
||||||
|
if (button==EDIT_BUTTON.ESC) then -- ESC
|
||||||
|
event = EVT_VIRTUAL_EXIT
|
||||||
|
elseif (button==EDIT_BUTTON.DEFAULT) then -- Default
|
||||||
|
event = EVT_VIRTUAL_ENTER_LONG
|
||||||
|
elseif (button==EDIT_BUTTON.DEC_10) then -- -10
|
||||||
|
event = EVT_VIRTUAL_PREV
|
||||||
|
editInc = -10
|
||||||
|
elseif (button==EDIT_BUTTON.DEC_1) then -- -1
|
||||||
|
event = EVT_VIRTUAL_PREV
|
||||||
|
editInc = -1
|
||||||
|
elseif (button==EDIT_BUTTON.INC_1) then -- +1
|
||||||
|
event = EVT_VIRTUAL_NEXT
|
||||||
|
editInc = 1
|
||||||
|
elseif (button==EDIT_BUTTON.INC_10) then -- + 10
|
||||||
|
event = EVT_VIRTUAL_NEXT
|
||||||
|
editInc = 10
|
||||||
|
elseif (button==EDIT_BUTTON.OK) then -- OK
|
||||||
|
event = EVT_VIRTUAL_ENTER
|
||||||
|
else
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return event, editInc
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Handle Events comming from the GUI
|
||||||
|
local function GUI_HandleEvent(event, touchState)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
local menu = ctx.Menu
|
||||||
|
local menuLines = ctx.MenuLines
|
||||||
|
local editInc = nil
|
||||||
|
|
||||||
|
if (IS_EDGETX) then
|
||||||
|
if (event == EVT_TOUCH_TAP and ctx.isEditing()) then -- Touch and Editing
|
||||||
|
local button = GUI_getTouchButton(touchState.x, touchState.y)
|
||||||
|
if (button) then
|
||||||
|
event, editInc = GUI_Translate_Edit_Buttons(button)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (event == EVT_TOUCH_TAP or event == EVT_TOUCH_FIRST) and not ctx.isEditing() then -- Touch and NOT editing
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_TOUCH_TAP %d,%d\n",dsmLib.phase2String(ctx.Phase),touchState.x, touchState.y) end
|
||||||
|
local button = GUI_getTouchButton(touchState.x, touchState.y)
|
||||||
|
if button then
|
||||||
|
-- Found a valid line
|
||||||
|
ctx.SelLine = button
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if event == EVT_TOUCH_TAP then -- EVT_TOUCH_FIRST only move focus
|
||||||
|
event = EVT_VIRTUAL_ENTER
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_EXIT then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_EXIT\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.Phase == PHASE.RX_VERSION then
|
||||||
|
dsmLib.ReleaseConnection() -- Just Exit the Script
|
||||||
|
else
|
||||||
|
if ctx.isEditing() then -- Editing a Line, need to restore original value
|
||||||
|
ctx.MenuLines[ctx.EditLine].Val = originalValue
|
||||||
|
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Update + Validate value in RX
|
||||||
|
ctx.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
|
||||||
|
else
|
||||||
|
dsmLib.ChangePhase(PHASE.EXIT)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_NEXT then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_NEXT\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.isEditing() then -- Editing a Line, need to inc the value
|
||||||
|
local line=ctx.MenuLines[ctx.EditLine]
|
||||||
|
dsmLib.Value_Add(line, editInc or GUI_RotEncVal(1))
|
||||||
|
else -- not editing, move selected line to NEXT
|
||||||
|
dsmLib.MoveSelectionLine(1)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_PREV then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_PREV\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.isEditing() then -- Editiing a line, need to dec the value
|
||||||
|
local line=ctx.MenuLines[ctx.EditLine]
|
||||||
|
dsmLib.Value_Add(line, editInc or GUI_RotEncVal(-1))
|
||||||
|
else -- not editing, move selected line to PREV
|
||||||
|
dsmLib.MoveSelectionLine(-1)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_ENTER_LONG then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",dsmLib.phase2String(ctx.Phase)) end
|
||||||
|
if ctx.isEditing() then
|
||||||
|
-- reset the value to default
|
||||||
|
dsmLib.Value_Default(menuLines[ctx.EditLine]) -- Update value in RX if needed
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == EVT_VIRTUAL_ENTER then
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER, SelLine=%d\n",dsmLib.phase2String(ctx.Phase), ctx.SelLine) end
|
||||||
|
if ctx.SelLine == dsmLib.BACK_BUTTON then -- Back
|
||||||
|
dsmLib.GotoMenu(menu.BackId)
|
||||||
|
elseif ctx.SelLine == dsmLib.NEXT_BUTTON then -- Next
|
||||||
|
dsmLib.GotoMenu(menu.NextId)
|
||||||
|
elseif ctx.SelLine == dsmLib.PREV_BUTTON then -- Prev
|
||||||
|
dsmLib.GotoMenu(menu.PrevId)
|
||||||
|
elseif menuLines[ctx.SelLine].ValId ~= 0 then -- Menu or Value
|
||||||
|
|
||||||
|
if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Navigate to Menu
|
||||||
|
if (SIMULATION_ON and menuLines[ctx.SelLine].ValId==0xFFFF) then
|
||||||
|
-- SPECIAL Simulation menu to Exit Simulation
|
||||||
|
GUI_SwitchSimulationOFF()
|
||||||
|
else
|
||||||
|
dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId) -- ValId is the MenuId to navigate to
|
||||||
|
end
|
||||||
|
else -- Enter on a Value
|
||||||
|
if ctx.isEditing() then -- already editing a Line????
|
||||||
|
ctx.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
|
||||||
|
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Request change the value on RX
|
||||||
|
else -- Edit the current value
|
||||||
|
ctx.EditLine = ctx.SelLine
|
||||||
|
originalValue = menuLines[ctx.SelLine].Val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function init_colors()
|
||||||
|
-- osName in OpenTX is nil, otherwise is EDGETX
|
||||||
|
local ver, radio, maj, minor, rev, osname = getVersion()
|
||||||
|
IS_EDGETX = osname~=nil
|
||||||
|
|
||||||
|
if (IS_EDGETX and USE_SPECKTRUM_COLORS) then
|
||||||
|
-- SPECKTRUM COLORS (only works on EDGETX)
|
||||||
|
-- TOOL HEADER
|
||||||
|
LCD_TOOL_HDR_COLOR = MENU_TITLE_COLOR
|
||||||
|
LCD_TOOL_HDR_BGCOLOR = TITLE_BGCOLOR
|
||||||
|
-- MENU HEADER
|
||||||
|
LCD_MENU_COLOR = WHITE
|
||||||
|
LCD_MENU_BGCOLOR = DARKGREY
|
||||||
|
-- LINE SELECTED
|
||||||
|
LCD_SELECTED_COLOR = WHITE
|
||||||
|
LCD_SELECTED_BGCOLOR = ORANGE
|
||||||
|
LCD_EDIT_BGCOLOR = WARNING_COLOR
|
||||||
|
-- NORMAL TEXT
|
||||||
|
LCD_NORMAL_COLOR = BLACK
|
||||||
|
LCD_DISABLE_COLOR = LIGHTGREY
|
||||||
|
LCD_DEBUG_COLOR = BLUE
|
||||||
|
-- NORMAL BOX FRAME COLOR
|
||||||
|
LCD_BOX_COLOR = LIGHTGREY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Init
|
||||||
|
local function DSM_Init()
|
||||||
|
init_colors()
|
||||||
|
dsmLib.Init(toolName) -- Initialize Library
|
||||||
|
return dsmLib.StartConnection()
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Main
|
||||||
|
local function DSM_Run(event,touchState)
|
||||||
|
local ctx = DSM_Context
|
||||||
|
|
||||||
|
if event == nil then
|
||||||
|
error("Cannot be run as a model script!")
|
||||||
|
dsmLib.LOG_close()
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
|
||||||
|
GUI_HandleEvent(event,touchState)
|
||||||
|
|
||||||
|
dsmLib.Send_Receive() -- Handle Send and Receive DSM Forward Programming Messages
|
||||||
|
|
||||||
|
local refreshInterval = REFRESH_GUI_MS
|
||||||
|
|
||||||
|
-- When using LCD BLINK attribute, we need faster refresh for BLINK to SHOW on LCD
|
||||||
|
if (ctx.Phase == PHASE.RX_VERSION) then -- Requesting RX Message Version usea BLINK?
|
||||||
|
ctx.Refresh_Display=true
|
||||||
|
refreshInterval = 20 -- 200ms
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Refresh display only if needed and no faster than 300ms, utilize more CPU to speedup DSM communications
|
||||||
|
if (ctx.Refresh_Display and (getTime()-lastRefresh) > refreshInterval) then --300ms from last refresh
|
||||||
|
GUI_Display()
|
||||||
|
ctx.Refresh_Display=false
|
||||||
|
lastRefresh=getTime()
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctx.Phase == PHASE.EXIT_DONE then
|
||||||
|
dsmLib.LOG_close()
|
||||||
|
return 2
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return { init=DSM_Init, run=DSM_Run }
|
1374
Lua_scripts/DSMLIB/DsmFwPrgLib.lua
Normal file
1374
Lua_scripts/DSMLIB/DsmFwPrgLib.lua
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Lua_scripts/DSMLIB/DsmFwPrgLib.luac
Normal file
BIN
Lua_scripts/DSMLIB/DsmFwPrgLib.luac
Normal file
Binary file not shown.
1075
Lua_scripts/DSMLIB/DsmFwPrgSIMLib.lua
Normal file
1075
Lua_scripts/DSMLIB/DsmFwPrgSIMLib.lua
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Lua_scripts/DSMLIB/DsmFwPrgSIMLib.luac
Normal file
BIN
Lua_scripts/DSMLIB/DsmFwPrgSIMLib.luac
Normal file
Binary file not shown.
44
Lua_scripts/DSMLIB/readme.txt
Normal file
44
Lua_scripts/DSMLIB/readme.txt
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
This script library is a rewrite of the original DSM forward programming Lua
|
||||||
|
Script. The goal is to make it easier to understand, mantain, and to
|
||||||
|
separate the GUI from the DSM Forward programming engine/logic
|
||||||
|
in this way, GUIs can evolve independent. OpenTX Gui, EdgeTx GUI, etc.
|
||||||
|
|
||||||
|
Code is based on the code/work by: Pascal Langer (Author of the Multi-Module)
|
||||||
|
Rewrite/Enhancements By: Francisco Arzu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Deployment:
|
||||||
|
/SCRIPTS/TOOLS/DsmFwdPrg_05_BaW.lua -- OpenTX/EdgeTx version, no touch (black/white radios)
|
||||||
|
/SCRIPTS/TOOLS/DsmFwdPrg_05_Color.lua -- EdgeTX/OpenTx Color version, +touch
|
||||||
|
/SCRIPTS/TOOLS/DSMLIB/ -- Libraries (ALL CAPITALS) to hide them from the Tools menu
|
||||||
|
/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lub -- DSM Protocol Message and Menu engine
|
||||||
|
/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lub -- Simulation of AR631 for GUI Development in Companion
|
||||||
|
|
||||||
|
/LOGS/dsm_log.txt -- Readable log of the last RX session, usefull for debuging new RX
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.5
|
||||||
|
- Make the code more readable and understadable
|
||||||
|
- Separate the DSM Forwards Programing logic from the GUI
|
||||||
|
- Log the comunnication with the RX on a /LOGS/dsm_log.txt to allow to debug it easier
|
||||||
|
and see the exchange of data between the RX/TX
|
||||||
|
- Created a black/white version with only Key/Roller Inputs (OTX)
|
||||||
|
- Created a nicer GUI for EdgeTX touchscreen color Radios
|
||||||
|
|
||||||
|
Known Problems:
|
||||||
|
1. When trying to Factory Reset an RX, even that navigation to menus seems OK, it did not reset.
|
||||||
|
Maybe another message needs to be sent to RX when reaching that page
|
||||||
|
2. When initially setting a new RX, there is a point where a menu navigates to MenuID=0x0001, this seems like a
|
||||||
|
special Save/Restart type of menu.. but it does not reset the RX. maybe another meesage needs to be send
|
||||||
|
3. Some Menu List line types (LINE_TYPE.LIST_MENU1), the range (min/max) seems to be incorrect, but cannot see in the data how to fix it
|
||||||
|
Some of the valid values are not even sequential, very spread apart. There has to be a list of valid options somewhere (in RX or config for each field).
|
||||||
|
4. The RX return unknow lines when requesting the Lines for a menu. Realy don't understand what they are for.
|
||||||
|
in some menus, seems to stay stuck in the same return line or no response to the request, making the RX reset/close the connection.
|
||||||
|
Did a fix to stop requesting the same menu line if the response is the same. This gives an empty menu, but does not reset the connection.
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.2
|
||||||
|
Original Version from Pascal Langer
|
||||||
|
|
||||||
|
|
@ -60,16 +60,14 @@ The OpenTX sensor "RSSI" is populated by the individual OpenTX telemetry protoco
|
|||||||
|
|
||||||
## DSM Forward Programming
|
## DSM Forward Programming
|
||||||
|
|
||||||
Navigation is mainly done using the scroll wheel and ENT. Short press on ENT will edit a value. When editing a value a long ENT press will restore the value to its default. To exit the script and terminate all current operations correctly short press RTN (if you don't do this the RX might not store the changes).
|
This is a work in progress. It's available for color(+touch) and B&W screens.
|
||||||
|
|
||||||
This is a work in progress. It's only available for color screens (Horus, TX16S, T16, T18...).
|
Work on OpenTX and EdgeTX. Located on the radio SD card under \SCRIPTS\TOOLS, make sure to copy the DSMLIB folder along with DSM FwdPrg_05_Color.lua or DSM FwdPrg_05_BW.lua.
|
||||||
|
|
||||||
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
|
|
||||||
|
|
||||||
Need OpenTX 2.3.10 nightly or above. Located on the radio SD card under \SCRIPTS\TOOLS.
|
|
||||||
|
|
||||||
[](https://www.youtube.com/watch?v=sjIaDw5j9nE)
|
[](https://www.youtube.com/watch?v=sjIaDw5j9nE)
|
||||||
|
|
||||||
|
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
|
||||||
|
|
||||||
## DSM PID Flight log gain parameters for Blade micros
|
## DSM PID Flight log gain parameters for Blade micros
|
||||||
|
|
||||||
Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display.
|
Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user