1 ---- #########################################################################
3 ---- # Copyright (C) OpenTX #
5 ---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
7 ---- # This program is free software; you can redistribute it and/or modify #
8 ---- # it under the terms of the GNU General Public License version 2 as #
9 ---- # published by the Free Software Foundation. #
11 ---- # This program is distributed in the hope that it will be useful #
12 ---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 ---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 ---- # GNU General Public License for more details. #
16 ---- #########################################################################
25 local refreshState
= 0
26 local refreshIndex
= 0
27 local calibrationState
= 0
29 local calibrationStep
= 0
32 local modifications
= {}
34 local calibrationFields
= {
35 {"X:", VALUE
, 0x9E, 0, -100, 100, "%"},
36 {"Y:", VALUE
, 0x9F, 0, -100, 100, "%"},
37 {"Z:", VALUE
, 0xA0, 0, -100, 100, "%"}
40 local function drawProgressBar()
41 local width
= (140 * refreshIndex
) / #fields
42 lcd
.drawRectangle(30, 1, 144, 6)
43 lcd
.drawFilledRectangle(32, 3, width
, 2);
46 -- Select the next or previous page
47 local function selectPage(step
)
48 page
= 1 + ((page
+ step
- 1 + #pages
) % #pages
)
54 -- Draw initial warning page
55 local function runWarningPage(event
)
57 lcd
.drawScreenTitle("SxR", page
, #pages
)
58 lcd
.drawText(0, 10, "Warning: this will start SxR calibration", SMLSIZE
)
59 lcd
.drawText(0, 20, "This need to be run only once. You need a SxR,", SMLSIZE
)
60 lcd
.drawText(0, 30, "power supply and a flat level surface (desk,...)", SMLSIZE
)
61 lcd
.drawText(0, 40, "Press [Enter] when ready", SMLSIZE
)
62 lcd
.drawText(0, 50, "Press [Exit] when cancel", SMLSIZE
)
63 if event
== EVT_ENTER_BREAK
then
66 elseif event
== EVT_EXIT_BREAK
then
72 -- Redraw the current page
73 local function redrawFieldsPage()
75 lcd
.drawScreenTitle("SxR", page
, #pages
)
77 if refreshIndex
< #fields
then
81 for index
= 1, 7, 1 do
82 local field
= fields
[pageOffset
+index
]
87 local attr
= current
== (pageOffset
+index
) and ((edit
== true and BLINK
or 0) + INVERS
) or 0
89 lcd
.drawText(0, 1+8*index
, field
[1])
91 if field
[4] == nil then
92 lcd
.drawText(COLUMN_2
, 1+8*index
, "---", attr
)
94 if field
[2] == VALUE
then
95 lcd
.drawNumber(COLUMN_2
, 1+8*index
, field
[4], LEFT
+ attr
)
96 elseif field
[2] == COMBO
then
97 if field
[4] >= 0 and field
[4] < #(field
[5]) then
98 lcd
.drawText(COLUMN_2
, 1+8*index
, field
[5][1+field
[4]]
, attr
)
105 local function telemetryRead(field
)
106 return sportTelemetryPush(0x17, 0x30, 0x0C30, field
)
109 local function telemetryWrite(field
, value
)
110 return sportTelemetryPush(0x17, 0x31, 0x0C30, field
+ value
*256)
113 local telemetryPopTimeout
= 0
114 local function refreshNext()
115 if refreshState
== 0 then
116 if calibrationState
== 1 then
117 if telemetryWrite(0x9D, calibrationStep
) == true then
120 telemetryPopTimeout
= getTime() + 80 -- normal delay is 500ms
122 elseif #modifications
> 0 then
123 telemetryWrite(modifications
[1][1], modifications
[1][2])
124 modifications
[1] = nil
125 elseif refreshIndex
< #fields
then
126 local field
= fields
[refreshIndex
+ 1]
127 if telemetryRead(field
[3]) == true then
129 telemetryPopTimeout
= getTime() + 80 -- normal delay is 500ms
132 elseif refreshState
== 1 then
133 local physicalId
, primId
, dataId
, value
= sportTelemetryPop()
134 if physicalId
== 0x1A and primId
== 0x32 and dataId
== 0x0C30 then
135 local fieldId
= value
% 256
136 if calibrationState
== 2 then
137 if fieldId
== 0x9D then
140 calibrationStep
= (calibrationStep
+ 1) % 7
143 local field
= fields
[refreshIndex
+ 1]
144 if fieldId
== field
[3] then
145 local value
= math
.floor(value
/ 256)
146 value
= bit32
.band(value
, 0xffff)
147 if field
[3] >= 0x9E and field
[3] <= 0xA0 then
148 local b1
= value
% 256
149 local b2
= math
.floor(value
/ 256)
151 value
= value
- bit32
.band(value
, 0x8000) * 2
153 if field
[2] == COMBO
and #field
== 6 then
154 for index
= 1, #(field
[6]), 1 do
155 if value
== field
[6][index
] then
160 elseif field
[2] == VALUE
and #field
== 8 then
161 value
= value
- field
[8] + field
[5]
163 fields
[refreshIndex
+ 1][4] = value
164 refreshIndex
= refreshIndex
+ 1
168 elseif getTime() > telemetryPopTimeout
then
175 local function updateField(field
)
176 local value
= field
[4]
177 if field
[2] == COMBO
and #field
== 6 then
178 value
= field
[6][1+value
]
179 elseif field
[2] == VALUE
and #field
== 8 then
180 value
= value
+ field
[8] - field
[5]
182 modifications
[#modifications
+1] = { field
[3], value
}
186 local function runFieldsPage(event
)
187 if event
== EVT_EXIT_BREAK
then -- exit script
189 elseif event
== EVT_ENTER_BREAK
then -- toggle editing/selecting current field
190 if fields
[current
][4] ~= nil then
192 if edit
== false then
193 updateField(fields
[current
])
197 if event
== EVT_PLUS_FIRST
or event
== EVT_ROT_RIGHT
or event
== EVT_PLUS_REPT
then
199 elseif event
== EVT_MINUS_FIRST
or event
== EVT_ROT_LEFT
or event
== EVT_MINUS_REPT
then
203 if event
== EVT_MINUS_FIRST
or event
== EVT_ROT_LEFT
then
205 elseif event
== EVT_PLUS_FIRST
or event
== EVT_ROT_RIGHT
then
213 local calibrationPositionsBitmaps
= { "bmp/up.bmp", "bmp/down.bmp", "bmp/left.bmp", "bmp/right.bmp", "bmp/forward.bmp", "bmp/back.bmp" }
215 local function runCalibrationPage(event
)
216 fields
= calibrationFields
217 if refreshIndex
== #fields
then
221 lcd
.drawScreenTitle("SxR", page
, #pages
)
222 if(calibrationStep
< 6) then
223 lcd
.drawText(0, 9, "Turn the SxR as shown", 0)
224 lcd
.drawPixmap(10, 19, calibrationPositionsBitmaps
[1 + calibrationStep
])
225 for index
= 1, 3, 1 do
226 local field
= fields
[index
]
227 lcd
.drawText(80, 12+10*index
, field
[1], 0)
228 lcd
.drawNumber(90, 12+10*index
, field
[4]/10, LEFT
+PREC2
)
231 local attr
= calibrationState
== 0 and INVERS
or 0
232 lcd
.drawText(0, 56, "Press [Enter] when ready", attr
)
234 lcd
.drawText(0, 9, "Calibration completed", 0)
235 lcd
.drawPixmap(10, 19, "bmp/done.bmp")
236 lcd
.drawText(0, 56, "Press [Exit] when ready", attr
)
238 if calibrationStep
> 6 and (event
== EVT_ENTER_BREAK
or event
== EVT_EXIT_BREAK
) then
240 elseif event
== EVT_ENTER_BREAK
then
242 elseif event
== EVT_EXIT_BREAK
then
243 if calibrationStep
> 0 then
251 local function init()
252 current
, edit
, refreshState
, refreshIndex
= 1, false, 0, 0
260 local function run(event
)
262 error("Cannot be run as a model script!")
264 elseif event
== EVT_PAGE_BREAK
then
266 elseif event
== EVT_PAGE_LONG
then
271 local result
= pages
[page
](event
)
277 return { init
=init
, run
=run
}