5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
22 #include "opentxeeprom.h"
23 #include "customdebug.h"
27 using namespace Board
;
29 #define IS_DBLEEPROM(board, version) ((IS_2560(board) || board==BOARD_M128) && version >= 213)
30 // Macro used for Gruvin9x board and M128 board between versions 213 and 214 (when there were stack overflows!)
31 #define IS_DBLRAM(board, version) ((IS_2560(board) && version >= 213) || (board==BOARD_M128 && version >= 213 && version <= 214))
33 #define HAS_PERSISTENT_TIMERS(board) (IS_ARM(board) || IS_2560(board))
34 #define MAX_VIEWS(board) (HAS_LARGE_LCD(board) ? 2 : 256)
35 #define MAX_POTS(board, version) (IS_HORUS(board) ? 3 : (IS_TARANIS_X7(board) ? 2 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 4 : (version >= 216 ? 3 : 2)) : 3)))
36 #define MAX_SLIDERS(board) (IS_HORUS(board) ? 4 : (IS_TARANIS_X7(board) ? 0 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 4 : 2) : 0)))
37 #define MAX_MOUSE_ANALOGS(board) (IS_HORUS(board) ? 2 : 0)
38 #define MAX_SWITCHES(board, version) (IS_HORUS(board) ? 8 : (IS_TARANIS_X7(board) ? 6 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 18 : 8) : 7)))
39 #define MAX_SWITCH_SLOTS(board, version) (IS_TARANIS_X9E(board) ? 32 : 8)
40 #define MAX_SWITCHES_POSITION(board, version) (IS_TARANIS_X7(board) ? 6*3 : (IS_TARANIS_X9E(board) ? 18*3 : (IS_HORUS_OR_TARANIS(board) ? 8*3 : 9)))
41 #define MAX_ROTARY_ENCODERS(board) (IS_2560(board) ? 2 : (IS_SKY9X(board) ? 1 : 0))
42 #define MAX_FLIGHT_MODES(board, version) (IS_ARM(board) ? 9 : (IS_DBLRAM(board, version) ? 6 : 5))
43 #define MAX_TIMERS(board, version) ((IS_ARM(board) && version >= 217) ? 3 : 2)
44 #define MAX_MIXERS(board, version) (IS_ARM(board) ? 64 : 32)
45 #define MAX_CHANNELS(board, version) (IS_ARM(board) ? 32 : 16)
46 #define MAX_TRIMS(board) (IS_HORUS(board) ? 6 : 4)
47 #define MAX_EXPOS(board, version) (IS_ARM(board) ? ((IS_HORUS_OR_TARANIS(board) && version >= 216) ? 64 : 32) : (IS_DBLRAM(board, version) ? 16 : 14))
48 #define MAX_LOGICAL_SWITCHES(board, version) (IS_ARM(board) ? (version >= 218 ? 64 : 32) : ((IS_DBLEEPROM(board, version) && version<217) ? 15 : 12))
49 #define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? (version >= 216 ? 64 : 32) : (IS_DBLEEPROM(board, version) ? 24 : 16))
50 #define MAX_CURVES(board, version) (IS_ARM(board) ? ((HAS_LARGE_LCD(board) && version >= 216) ? 32 : 16) : 8)
51 #define MAX_GVARS(board, version) ((IS_ARM(board) && version >= 216) ? 9 : 5)
52 #define MAX_SCRIPTS(board) (IS_HORUS(board) ? 9 : 7)
53 #define MAX_TELEMETRY_SENSORS(board, version) (32)
54 #define NUM_PPM_INPUTS(board, version) ((IS_ARM(board) && version >= 216) ? 16 : 8)
55 #define ROTENC_COUNT(board, version) (IS_ARM(board) ? ((IS_STM32(board) && version >= 218) ? 0 : 1) : (IS_2560(board) ? 2 : 0))
56 #define MAX_AUX_TRIMS(board) (IS_HORUS(board) ? 2 : 0)
58 #define IS_AFTER_RELEASE_21_MARCH_2013(board, version) (version >= 214 || (!IS_ARM(board) && version >= 213))
59 #define IS_AFTER_RELEASE_23_MARCH_2013(board, version) (version >= 214 || (board==BOARD_STOCK && version >= 213))
61 inline int switchIndex(int i
, Board::Type board
, unsigned int version
)
63 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
64 if (!IS_HORUS_OR_TARANIS(board
) && afterrelease21March2013
)
65 return (i
<=3 ? i
+3 : (i
<=6 ? i
-3 : i
));
70 class SwitchesConversionTable
: public ConversionTable
{
73 SwitchesConversionTable(Board::Type board
, unsigned int version
, bool timer
=false)
79 for (int i
=0; i
<5; i
++) {
80 addConversion(RawSwitch(SWITCH_TYPE_TIMER_MODE
, i
), val
++);
84 addConversion(RawSwitch(SWITCH_TYPE_NONE
), val
++);
87 for (int i
=1; i
<=MAX_SWITCHES_POSITION(board
, version
); i
++) {
88 int s
= switchIndex(i
, board
, version
);
89 if (IS_TARANIS(board
) && version
< 217) {
90 // SF positions 16 and 17 => 16 and 18
91 // SH positions 21 and 22 => 22 and 24
92 if (s
== 17 || s
== 23) {
96 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
);
97 addImportConversion(RawSwitch(SWITCH_TYPE_SWITCH
, 21+22-s
), -val
+offset
);
98 addExportConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
+offset
);
103 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
);
104 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
+offset
);
108 if (IS_HORUS_OR_TARANIS(board
) && version
>= 216) {
109 for (int i
=1; i
<=MAX_POTS(board
, version
)*6; i
++) {
110 addConversion(RawSwitch(SWITCH_TYPE_MULTIPOS_POT
, -i
), -val
+offset
);
111 addConversion(RawSwitch(SWITCH_TYPE_MULTIPOS_POT
, i
), val
++);
115 if (version
>= 216) {
116 for (int i
=1; i
<=2*MAX_TRIMS(board
); i
++) {
117 addConversion(RawSwitch(SWITCH_TYPE_TRIM
, -i
), -val
+offset
);
118 addConversion(RawSwitch(SWITCH_TYPE_TRIM
, i
), val
++);
122 if (version
>= 216) {
123 for (int i
=1; i
<=MAX_ROTARY_ENCODERS(board
); i
++) {
124 addConversion(RawSwitch(SWITCH_TYPE_ROTARY_ENCODER
, -i
), -val
+offset
);
125 addConversion(RawSwitch(SWITCH_TYPE_ROTARY_ENCODER
, i
), val
++);
129 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
130 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, -i
), -val
+offset
);
131 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
134 addConversion(RawSwitch(SWITCH_TYPE_OFF
), -val
+offset
);
135 addConversion(RawSwitch(SWITCH_TYPE_ON
), val
++);
137 if (version
>= 216) {
138 addConversion(RawSwitch(SWITCH_TYPE_ONE
, -1), -val
+offset
);
139 addConversion(RawSwitch(SWITCH_TYPE_ONE
, 1), val
++);
141 for (int i
=1; i
<=MAX_FLIGHT_MODES(board
, version
); i
++) {
142 addConversion(RawSwitch(SWITCH_TYPE_FLIGHT_MODE
, -i
), -val
+offset
);
143 addConversion(RawSwitch(SWITCH_TYPE_FLIGHT_MODE
, i
), val
++);
148 if (IS_ARM(board
) && version
>= 218) {
149 addConversion(RawSwitch(SWITCH_TYPE_TELEMETRY
, -1), -val
+offset
);
150 addConversion(RawSwitch(SWITCH_TYPE_TELEMETRY
, 1), val
++);
151 for (int i
=1; i
<=CPN_MAX_SENSORS
; i
++) {
152 addConversion(RawSwitch(SWITCH_TYPE_SENSOR
, -i
), -val
+offset
);
153 addConversion(RawSwitch(SWITCH_TYPE_SENSOR
, i
), val
++);
158 // previous "moment" switches
159 for (int i
=1; i
<=MAX_SWITCHES_POSITION(board
, version
); i
++) {
160 int s
= switchIndex(i
, board
, version
);
161 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
164 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
165 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
168 // previous "One" switch
169 addConversion(RawSwitch(SWITCH_TYPE_ON
), val
++);
176 void addConversion(const RawSwitch
& sw
, const int b
)
178 ConversionTable::addConversion(sw
.toValue(), b
);
181 void addImportConversion(const RawSwitch
& sw
, const int b
)
183 ConversionTable::addImportConversion(sw
.toValue(), b
);
186 void addExportConversion(const RawSwitch
& sw
, const int b
)
188 ConversionTable::addExportConversion(sw
.toValue(), b
);
193 Cache(Board::Type board
, unsigned int version
, unsigned long flags
, SwitchesConversionTable
* table
):
201 unsigned int version
;
203 SwitchesConversionTable
* table
;
206 static std::list
<Cache
> internalCache
;
210 static SwitchesConversionTable
* getInstance(Board::Type board
, unsigned int version
, unsigned long flags
=0)
212 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
213 Cache
& element
= *it
;
214 if (element
.board
== board
&& element
.version
== version
&& element
.flags
== flags
)
215 return element
.table
;
218 Cache
element(board
, version
, flags
, new SwitchesConversionTable(board
, version
, flags
));
219 internalCache
.push_back(element
);
220 return element
.table
;
222 static void Cleanup()
224 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
225 Cache
& element
= *it
;
227 delete element
.table
;
229 internalCache
.clear();
233 std::list
<SwitchesConversionTable::Cache
> SwitchesConversionTable::internalCache
;
235 #define FLAG_NONONE 0x01
236 #define FLAG_NOSWITCHES 0x02
237 #define FLAG_NOTELEMETRY 0x04
239 class SourcesConversionTable
: public ConversionTable
{
242 SourcesConversionTable(Board::Type board
, unsigned int version
, unsigned int variant
, unsigned long flags
=0)
244 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
248 if (!(flags
& FLAG_NONONE
)) {
249 addConversion(RawSource(SOURCE_TYPE_NONE
), val
++);
252 if ((IS_ARM(board
) && version
>= 218) || (IS_STM32(board
) && version
>= 216)) {
253 for (int i
=0; i
<32; i
++) {
254 addConversion(RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, i
), val
++);
258 if (IS_STM32(board
) && version
>= 216) {
259 for (int i
= 0; i
< MAX_SCRIPTS(board
); i
++) {
260 for (int j
= 0; j
< 6; j
++) {
261 addConversion(RawSource(SOURCE_TYPE_LUA_OUTPUT
, i
* 16 + j
), val
++);
266 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_POTS(board
, version
)+MAX_SLIDERS(board
)+MAX_MOUSE_ANALOGS(board
); i
++) {
267 addConversion(RawSource(SOURCE_TYPE_STICK
, i
), val
++);
270 for (int i
=0; i
<MAX_ROTARY_ENCODERS(board
); i
++) {
271 addConversion(RawSource(SOURCE_TYPE_ROTARY_ENCODER
, 0), val
++);
274 if (!afterrelease21March2013
) {
275 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
276 addConversion(RawSource(SOURCE_TYPE_TRIM
, i
), val
++);
280 addConversion(RawSource(SOURCE_TYPE_MAX
), val
++);
282 if (afterrelease21March2013
) {
283 for (int i
=0; i
<3; i
++)
284 addConversion(RawSource(SOURCE_TYPE_CYC
, i
), val
++);
287 if (afterrelease21March2013
) {
288 for (int i
=0; i
<MAX_TRIMS(board
); i
++)
289 addConversion(RawSource(SOURCE_TYPE_TRIM
, i
), val
++);
292 addConversion(RawSource(SOURCE_TYPE_SWITCH
, 0), val
++);
294 if (!(flags
& FLAG_NOSWITCHES
)) {
295 if (afterrelease21March2013
) {
296 for (int i
=1; i
<MAX_SWITCHES(board
, version
); i
++)
297 addConversion(RawSource(SOURCE_TYPE_SWITCH
, i
), val
++);
300 for (int i
=1; i
<=9; i
++) {
302 addConversion(RawSource(SOURCE_TYPE_SWITCH
, 0), val
++);
304 addConversion(RawSource(SOURCE_TYPE_SWITCH
, i
), val
++);
307 for (int i
=0; i
<MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
308 addConversion(RawSource(SOURCE_TYPE_CUSTOM_SWITCH
, i
), val
++);
312 if (!afterrelease21March2013
) {
313 for (int i
=0; i
<3; i
++) {
314 addConversion(RawSource(SOURCE_TYPE_CYC
, i
), val
++);
318 for (int i
=0; i
<NUM_PPM_INPUTS(board
, version
); i
++) {
319 addConversion(RawSource(SOURCE_TYPE_PPM
, i
), val
++);
322 for (int i
=0; i
<MAX_CHANNELS(board
, version
); i
++) {
323 addConversion(RawSource(SOURCE_TYPE_CH
, i
), val
++);
326 if (!(flags
& FLAG_NOTELEMETRY
)) {
327 if (IS_ARM(board
) && version
>= 217) {
328 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++)
329 addConversion(RawSource(SOURCE_TYPE_GVAR
, i
), val
++);
330 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 0), val
++); // BATT
331 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 1), val
++); // TIME
333 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 2), val
++); // Timer1
334 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 3), val
++); // Timer2
335 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 4), val
++); // Timer3
336 for (int i
=0; i
<CPN_MAX_SENSORS
*3; ++i
) {
337 addConversion(RawSource(SOURCE_TYPE_TELEMETRY
, i
), val
++);
341 if (afterrelease21March2013
) {
342 if ((board
!= BOARD_STOCK
&& (board
!=BOARD_M128
|| version
<215)) || (variant
& GVARS_VARIANT
)) {
343 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
344 addConversion(RawSource(SOURCE_TYPE_GVAR
, i
), val
++);
349 for (int i
=0; i
<TELEMETRY_SOURCE_ACC
; i
++) {
351 if (i
==TELEMETRY_SOURCE_TX_TIME
|| i
==TELEMETRY_SOURCE_SWR
|| i
==TELEMETRY_SOURCE_A3
|| i
==TELEMETRY_SOURCE_A4
|| i
==TELEMETRY_SOURCE_ASPEED
|| i
==TELEMETRY_SOURCE_DTE
|| i
==TELEMETRY_SOURCE_CELL_MIN
|| i
==TELEMETRY_SOURCE_CELLS_MIN
|| i
==TELEMETRY_SOURCE_VFAS_MIN
)
354 if (!IS_ARM(board
)) {
355 if (i
==TELEMETRY_SOURCE_TX_TIME
|| i
==TELEMETRY_SOURCE_SWR
|| i
==TELEMETRY_SOURCE_A3
|| i
==TELEMETRY_SOURCE_A4
|| i
==TELEMETRY_SOURCE_A3_MIN
|| i
==TELEMETRY_SOURCE_A4_MIN
)
358 addConversion(RawSource(SOURCE_TYPE_TELEMETRY
, i
), val
++);
359 if (version
>= 216 && IS_ARM(board
)) {
360 if (i
==TELEMETRY_SOURCE_RSSI_RX
)
362 if (i
==TELEMETRY_SOURCE_TX_TIME
)
364 if (i
==TELEMETRY_SOURCE_DTE
)
366 if (i
==TELEMETRY_SOURCE_POWER_MAX
)
376 void addConversion(const RawSource
& source
, const int b
)
378 ConversionTable::addConversion(source
.toValue(), b
);
383 Cache(Board::Type board
, unsigned int version
, unsigned int variant
, unsigned long flags
, SourcesConversionTable
* table
):
392 unsigned int version
;
393 unsigned int variant
;
395 SourcesConversionTable
* table
;
397 static std::list
<Cache
> internalCache
;
401 static SourcesConversionTable
* getInstance(Board::Type board
, unsigned int version
, unsigned int variant
, unsigned long flags
=0)
403 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
404 Cache
& element
= *it
;
405 if (element
.board
== board
&& element
.version
== version
&& element
.variant
== variant
&& element
.flags
== flags
)
406 return element
.table
;
409 Cache
element(board
, version
, variant
, flags
, new SourcesConversionTable(board
, version
, variant
, flags
));
410 internalCache
.push_back(element
);
411 return element
.table
;
413 static void Cleanup()
415 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
416 Cache
& element
= *it
;
418 delete element
.table
;
420 internalCache
.clear();
424 std::list
<SourcesConversionTable::Cache
> SourcesConversionTable::internalCache
;
426 void OpenTxEepromCleanup(void)
428 SourcesConversionTable::Cleanup();
429 SwitchesConversionTable::Cleanup();
433 class SwitchField
: public ConversionField
< SignedField
<N
> > {
435 SwitchField(DataField
* parent
, RawSwitch
& sw
, Board::Type board
, unsigned int version
, unsigned long flags
=0):
436 ConversionField
< SignedField
<N
> >(parent
, _switch
, SwitchesConversionTable::getInstance(board
, version
, flags
), QObject::tr("Switch").toLatin1(),
437 QObject::tr("Switch ").toLatin1() + sw
.toString(board
) + QObject::tr(" cannot be exported on this board!").toLatin1()),
444 virtual ~SwitchField()
448 virtual void beforeExport()
450 _switch
= sw
.toValue();
451 ConversionField
< SignedField
<N
> >::beforeExport();
454 virtual void afterImport()
456 ConversionField
< SignedField
<N
> >::afterImport();
457 sw
= RawSwitch(_switch
);
458 qCDebug(eepromImport
) << QString("imported %1: %2").arg(ConversionField
< SignedField
<N
> >::internalField
.getName()).arg(sw
.toString(board
));
467 class TelemetrySourcesConversionTable
: public ConversionTable
{
470 TelemetrySourcesConversionTable(Board::Type board
, unsigned int version
)
474 if (IS_AFTER_RELEASE_21_MARCH_2013(board
, version
)) {
475 addConversion(0, val
++);
478 addConversion(1+TELEMETRY_SOURCE_TX_BATT
, val
++);
479 if (IS_ARM(board
) && version
>= 216) {
480 addConversion(1+TELEMETRY_SOURCE_TX_TIME
, val
++);
481 for (int i
=0; i
<5; i
++)
482 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
484 addConversion(1+TELEMETRY_SOURCE_TIMER1
, val
++);
485 addConversion(1+TELEMETRY_SOURCE_TIMER2
, val
++);
486 if (IS_ARM(board
) && version
>= 217)
487 addConversion(1+TELEMETRY_SOURCE_TIMER3
, val
++);
488 if (IS_ARM(board
) && version
>= 216)
489 addConversion(1+TELEMETRY_SOURCE_SWR
, val
++);
490 addConversion(1+TELEMETRY_SOURCE_RSSI_TX
, val
++);
491 addConversion(1+TELEMETRY_SOURCE_RSSI_RX
, val
++);
492 if (IS_ARM(board
) && version
>= 216)
493 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
494 addConversion(1+TELEMETRY_SOURCE_A1
, val
++);
495 addConversion(1+TELEMETRY_SOURCE_A2
, val
++);
496 if (IS_ARM(board
) && version
>= 216) {
497 addConversion(1+TELEMETRY_SOURCE_A3
, val
++);
498 addConversion(1+TELEMETRY_SOURCE_A4
, val
++);
500 addConversion(1+TELEMETRY_SOURCE_ALT
, val
++);
501 addConversion(1+TELEMETRY_SOURCE_RPM
, val
++);
502 addConversion(1+TELEMETRY_SOURCE_FUEL
, val
++);
503 addConversion(1+TELEMETRY_SOURCE_T1
, val
++);
504 addConversion(1+TELEMETRY_SOURCE_T2
, val
++);
505 addConversion(1+TELEMETRY_SOURCE_SPEED
, val
++);
506 addConversion(1+TELEMETRY_SOURCE_DIST
, val
++);
507 addConversion(1+TELEMETRY_SOURCE_GPS_ALT
, val
++);
508 addConversion(1+TELEMETRY_SOURCE_CELL
, val
++);
509 addConversion(1+TELEMETRY_SOURCE_CELLS_SUM
, val
++);
510 addConversion(1+TELEMETRY_SOURCE_VFAS
, val
++);
511 addConversion(1+TELEMETRY_SOURCE_CURRENT
, val
++);
512 addConversion(1+TELEMETRY_SOURCE_CONSUMPTION
, val
++);
513 addConversion(1+TELEMETRY_SOURCE_POWER
, val
++);
514 addConversion(1+TELEMETRY_SOURCE_ACCX
, val
++);
515 addConversion(1+TELEMETRY_SOURCE_ACCY
, val
++);
516 addConversion(1+TELEMETRY_SOURCE_ACCZ
, val
++);
517 addConversion(1+TELEMETRY_SOURCE_HDG
, val
++);
518 addConversion(1+TELEMETRY_SOURCE_VERTICAL_SPEED
, val
++);
519 if (version
>= 216) {
520 addConversion(1+TELEMETRY_SOURCE_ASPEED
, val
++);
521 addConversion(1+TELEMETRY_SOURCE_DTE
, val
++);
523 if (IS_ARM(board
) && version
>= 216) {
524 for (int i
=0; i
<5; i
++)
525 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
527 addConversion(1+TELEMETRY_SOURCE_A1_MIN
, val
++);
528 addConversion(1+TELEMETRY_SOURCE_A2_MIN
, val
++);
529 if (IS_ARM(board
) && version
>= 216) {
530 addConversion(1+TELEMETRY_SOURCE_A3_MIN
, val
++);
531 addConversion(1+TELEMETRY_SOURCE_A4_MIN
, val
++);
533 addConversion(1+TELEMETRY_SOURCE_ALT_MIN
, val
++);
534 addConversion(1+TELEMETRY_SOURCE_ALT_MAX
, val
++);
535 addConversion(1+TELEMETRY_SOURCE_RPM_MAX
, val
++);
536 addConversion(1+TELEMETRY_SOURCE_T1_MAX
, val
++);
537 addConversion(1+TELEMETRY_SOURCE_T2_MAX
, val
++);
538 addConversion(1+TELEMETRY_SOURCE_SPEED_MAX
, val
++);
539 addConversion(1+TELEMETRY_SOURCE_DIST_MAX
, val
++);
540 if (version
>= 216) {
541 addConversion(1+TELEMETRY_SOURCE_ASPEED_MAX
, val
++);
542 addConversion(1+TELEMETRY_SOURCE_CELL_MIN
, val
++);
543 addConversion(1+TELEMETRY_SOURCE_CELLS_MIN
, val
++);
544 addConversion(1+TELEMETRY_SOURCE_VFAS_MIN
, val
++);
546 addConversion(1+TELEMETRY_SOURCE_CURRENT_MAX
, val
++);
547 addConversion(1+TELEMETRY_SOURCE_POWER_MAX
, val
++);
548 if (IS_ARM(board
) && version
>= 216) {
549 for (int i
=0; i
<5; i
++)
550 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
552 addConversion(1+TELEMETRY_SOURCE_ACC
, val
++);
553 addConversion(1+TELEMETRY_SOURCE_GPS_TIME
, val
++);
558 class TelemetrySourceField
: public ConversionField
< UnsignedField
<N
> > {
560 TelemetrySourceField(DataField
* parent
, RawSource
& source
, Board::Type board
, unsigned int version
):
561 ConversionField
< UnsignedField
<N
> >(parent
, _source
, &conversionTable
, "Telemetry source"),
562 conversionTable(board
, version
),
570 virtual ~TelemetrySourceField()
574 virtual void beforeExport()
576 _source
= (source
.type
== SOURCE_TYPE_TELEMETRY
? source
.index
+1 : 0);
577 ConversionField
< UnsignedField
<N
> >::beforeExport();
580 virtual void afterImport()
582 ConversionField
< UnsignedField
<N
> >::afterImport();
583 source
= (_source
== 0 ? RawSource(0) : RawSource(SOURCE_TYPE_TELEMETRY
, _source
-1));
584 qCDebug(eepromImport
) << QString("imported %1: %2").arg(ConversionField
< UnsignedField
<N
> >::internalField
.getName()).arg(source
.toString());
588 TelemetrySourcesConversionTable conversionTable
;
591 unsigned int version
;
592 unsigned int _source
;
596 class SourceField
: public ConversionField
< UnsignedField
<N
> > {
598 SourceField(DataField
* parent
, RawSource
& source
, Board::Type board
, unsigned int version
, unsigned int variant
, unsigned long flags
=0):
599 ConversionField
< UnsignedField
<N
> >(parent
, _source
, SourcesConversionTable::getInstance(board
, version
, variant
, flags
),
600 "Source", QObject::tr("Source %1 cannot be exported on this board!").arg(source
.toString())),
606 virtual ~SourceField()
610 virtual void beforeExport()
612 _source
= source
.toValue();
613 ConversionField
< UnsignedField
<N
> >::beforeExport();
616 virtual void afterImport()
618 ConversionField
< UnsignedField
<N
> >::afterImport();
619 source
= RawSource(_source
);
620 qCDebug(eepromImport
) << QString("imported %1: %2").arg(ConversionField
< UnsignedField
<N
> >::internalField
.getName()).arg(source
.toString());
625 unsigned int _source
;
629 int smallGvarImport(int gvar
)
632 gvar
= 128 + gvar
+ 10000;
634 else if (gvar
> 10000) {
635 gvar
= -128 +gvar
- 10001;
640 int smallGvarExport(int gvar
)
643 gvar
= gvar
- 128 - 10000;
645 else if (gvar
< -110) {
646 gvar
= gvar
+ 128 + 10001;
651 void splitGvarParam(const int gvar
, int & _gvar
, unsigned int & _gvarParam
, const Board::Type board
, const int version
)
653 if (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) {
656 _gvar
= 256 + gvar
+ 10000;
658 else if (gvar
> 10000) {
660 _gvar
= gvar
- 10001;
663 if (gvar
< 0) _gvarParam
= 1;
665 _gvar
= gvar
; // save routine throws away all unused bits; therefore no 2er complement compensation needed here
671 _gvar
= gvar
+ 10000;
673 else if (gvar
> 10000) {
675 _gvar
= gvar
- 10001;
684 void concatGvarParam(int & gvar
, const int _gvar
, const unsigned int _gvarParam
, const Board::Type board
, const int version
)
686 if (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) {
688 if (gvar
<0) gvar
+=256; // remove 2er complement, because 8bit part is in this case unsigned
689 if (_gvarParam
) { // here is the real sign bit
690 gvar
|=-256; // set all higher bits to simulate negative value
694 gvar
= gvar
-256 - 10000;
695 } else if (gvar
<-245) {
696 gvar
= gvar
+256 + 10001;
700 if (_gvarParam
== 0) {
703 else if (_gvar
>= 0) {
704 gvar
= 10001 + _gvar
;
707 gvar
= -10000 + _gvar
;
712 void exportGvarParam(const int gvar
, int & _gvar
, int version
)
714 int GV1
= (version
>= 217 ? 1024 : (version
>= 216 ? 4096 : 512));
717 _gvar
= GV1
+ gvar
+ 10000;
719 else if (gvar
> 10000) {
720 _gvar
= GV1
+ gvar
- 10001;
727 void importGvarParam(int & gvar
, const int _gvar
, int version
)
729 int GV1
= (version
>= 217 ? 1024 : (version
>= 216 ? 4096 : 512));
732 gvar
= 10001 + _gvar
- GV1
;
734 else if (_gvar
>= GV1
-9) {
735 gvar
= -10000 + _gvar
- GV1
;
737 else if (_gvar
< -GV1
) {
738 gvar
= -10000 + _gvar
+ GV1
+ 1;
740 else if (_gvar
< -GV1
+9) {
741 gvar
= 10000 + _gvar
+ GV1
+ 1;
747 // qDebug() << QString("import") << _gvar << gvar;
750 class CurveReferenceField
: public TransformedField
{
752 CurveReferenceField(DataField
* parent
, CurveReference
& curve
, Board::Type board
, unsigned int version
):
753 TransformedField(parent
, internalField
),
759 internalField
.Append(new UnsignedField
<8>(this, _curve_type
));
760 internalField
.Append(new SignedField
<8>(this, _curve_value
));
763 virtual void beforeExport()
765 if (curve
.value
!= 0) {
766 _curve_type
= (unsigned int)curve
.type
;
767 _curve_value
= smallGvarImport(curve
.value
);
775 virtual void afterImport()
777 curve
.type
= (CurveReference::CurveRefType
)_curve_type
;
778 curve
.value
= smallGvarExport(_curve_value
);
779 qCDebug(eepromImport
) << QString("imported CurveReference(%1)").arg(curve
.toString());
783 StructField internalField
;
784 CurveReference
& curve
;
785 unsigned int _curve_type
;
789 static int exportHeliInversionWeight(int source
) {
790 return (source
< 0) ? 1 : 0;
793 static int importHeliInversionWeight(int source
) {
794 return source
? -100: 100;
797 class HeliField
: public StructField
{
799 HeliField(DataField
* parent
, SwashRingData
& heli
, Board::Type board
, unsigned int version
, unsigned int variant
):
800 StructField(parent
, "Heli")
802 if ((IS_ARM(board
) && version
>= 218) || (IS_STM32(board
) && version
>= 217)) {
803 Append(new UnsignedField
<8>(this, heli
.type
));
804 Append(new UnsignedField
<8>(this, heli
.value
));
805 Append(new SourceField
<8>(this, heli
.collectiveSource
, board
, version
, variant
));
806 Append(new SourceField
<8>(this, heli
.aileronSource
, board
, version
, variant
));
807 Append(new SourceField
<8>(this, heli
.elevatorSource
, board
, version
, variant
));
808 Append(new SignedField
<8>(this, heli
.collectiveWeight
));
809 Append(new SignedField
<8>(this, heli
.aileronWeight
));
810 Append(new SignedField
<8>(this, heli
.elevatorWeight
));
813 Append(new ConversionField
< SignedField
<1> >(this, heli
.elevatorWeight
, exportHeliInversionWeight
, importHeliInversionWeight
));
814 Append(new ConversionField
< SignedField
<1> >(this, heli
.aileronWeight
, exportHeliInversionWeight
, importHeliInversionWeight
));
815 Append(new ConversionField
< SignedField
<1> >(this, heli
.collectiveWeight
, exportHeliInversionWeight
, importHeliInversionWeight
));
816 Append(new UnsignedField
<5>(this, heli
.type
));
817 Append(new SourceField
<8>(this, heli
.collectiveSource
, board
, version
, variant
));
818 //, FLAG_NOSWITCHES)); Fix shift in collective
819 Append(new UnsignedField
<8>(this, heli
.value
));
824 class FlightModeField
: public TransformedField
{
826 FlightModeField(DataField
* parent
, FlightModeData
& phase
, int index
, Board::Type board
, unsigned int version
):
827 TransformedField(parent
, internalField
),
828 internalField(this, "FlightMode"),
833 rotencCount(ROTENC_COUNT(board
, version
))
835 if (board
== BOARD_STOCK
|| (board
==BOARD_M128
&& version
>=215)) {
836 // On stock we use 10bits per trim
837 for (int i
=0; i
<CPN_MAX_STICKS
; i
++)
838 internalField
.Append(new SignedField
<8>(this, trimBase
[i
]));
839 for (int i
=0; i
<CPN_MAX_STICKS
; i
++)
840 internalField
.Append(new SignedField
<2>(this, trimExt
[i
]));
842 else if (IS_ARM(board
) && version
>= 218) {
843 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_AUX_TRIMS(board
); i
++) {
844 internalField
.Append(new SignedField
<11>(this, phase
.trim
[i
]));
845 internalField
.Append(new UnsignedField
<5>(this, trimMode
[i
]));
848 else if (IS_TARANIS(board
) && version
>= 216) {
849 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
850 internalField
.Append(new SignedField
<11>(this, phase
.trim
[i
]));
851 internalField
.Append(new UnsignedField
<5>(this, trimMode
[i
]));
855 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
856 internalField
.Append(new SignedField
<16>(this, trimBase
[i
]));
859 if (IS_ARM(board
) && version
>= 218) {
860 if (HAS_LARGE_LCD(board
))
861 internalField
.Append(new ZCharField
<10>(this, phase
.name
, "Flight mode name"));
863 internalField
.Append(new ZCharField
<6>(this, phase
.name
, "Flight mode name"));
864 internalField
.Append(new SwitchField
<9>(this, phase
.swtch
, board
, version
));
865 internalField
.Append(new SpareBitsField
<7>(this));
868 internalField
.Append(new SwitchField
<8>(this, phase
.swtch
, board
, version
));
869 if (HAS_LARGE_LCD(board
))
870 internalField
.Append(new ZCharField
<10>(this, phase
.name
));
872 internalField
.Append(new ZCharField
<6>(this, phase
.name
));
874 if (IS_ARM(board
) && version
>= 214) {
875 internalField
.Append(new UnsignedField
<8>(this, phase
.fadeIn
));
876 internalField
.Append(new UnsignedField
<8>(this, phase
.fadeOut
));
879 internalField
.Append(new UnsignedField
<4>(this, phase
.fadeIn
));
880 internalField
.Append(new UnsignedField
<4>(this, phase
.fadeOut
));
883 for (int i
=0; i
<rotencCount
; i
++) {
884 internalField
.Append(new SignedField
<16>(this, phase
.rotaryEncoders
[i
]));
887 if (board
!= BOARD_STOCK
&& (board
!= BOARD_M128
|| version
< 215)) {
888 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
889 internalField
.Append(new SignedField
<16>(this, phase
.gvars
[i
]));
894 virtual void beforeExport()
896 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_AUX_TRIMS(board
); i
++) {
897 if ((IS_HORUS_OR_TARANIS(board
) && version
>= 216) || (IS_ARM(board
) && version
>= 218)) {
898 if (phase
.trimMode
[i
] < 0)
899 trimMode
[i
] = TRIM_MODE_NONE
;
901 trimMode
[i
] = 2*phase
.trimRef
[i
] + phase
.trimMode
[i
];
905 if (phase
.trimMode
[i
] < 0)
907 else if (phase
.trimRef
[i
] != index
)
908 trim
= 501 + phase
.trimRef
[i
] - (phase
.trimRef
[i
] > index
? 1 : 0);
910 trim
= std::max(-500, std::min(500, phase
.trim
[i
]));
911 if (board
== BOARD_STOCK
|| (board
== BOARD_M128
&& version
>= 215)) {
912 trimBase
[i
] = trim
>> 2;
913 trimExt
[i
] = (trim
& 0x03);
922 virtual void afterImport()
924 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_AUX_TRIMS(board
); i
++) {
925 if ((IS_HORUS_OR_TARANIS(board
) && version
>= 216) || (IS_ARM(board
) && version
>= 218)) {
926 if (trimMode
[i
] == TRIM_MODE_NONE
) {
927 phase
.trimMode
[i
] = -1;
930 phase
.trimMode
[i
] = trimMode
[i
] % 2;
931 phase
.trimRef
[i
] = trimMode
[i
] / 2;
935 if (phase
.swtch
== RawSwitch(SWITCH_TYPE_NONE
) && index
> 0) {
936 phase
.trimRef
[i
] = 0;
937 phase
.trimMode
[i
] = 0;
942 if (board
== BOARD_STOCK
|| (board
== BOARD_M128
&& version
>= 215))
943 trim
= ((trimBase
[i
]) << 2) + (trimExt
[i
] & 0x03);
947 phase
.trimRef
[i
] = trim
- 501;
948 if (phase
.trimRef
[i
] >= index
)
949 phase
.trimRef
[i
] += 1;
950 phase
.trimMode
[i
] = 0;
954 phase
.trimRef
[i
] = index
/*own trim*/;
955 phase
.trimMode
[i
] = 0;
956 phase
.trim
[i
] = trim
;
961 qCDebug(eepromImport
) << QString("imported %1: '%2'").arg(internalField
.getName()).arg(phase
.name
);
965 StructField internalField
;
966 FlightModeData
& phase
;
969 unsigned int version
;
971 int trimBase
[CPN_MAX_TRIMS
];
972 int trimExt
[CPN_MAX_TRIMS
];
973 unsigned int trimMode
[CPN_MAX_TRIMS
];
976 class MixField
: public TransformedField
{
978 MixField(DataField
* parent
, MixData
& mix
, Board::Type board
, unsigned int version
, ModelData
* model
):
979 TransformedField(parent
, internalField
),
980 internalField(this, "Mix"),
986 if (IS_ARM(board
) && version
>= 218) {
987 internalField
.Append(new SignedField
<11>(this, _weight
));
988 internalField
.Append(new UnsignedField
<5>(this, _destCh
));
989 internalField
.Append(new SourceField
<10>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
990 internalField
.Append(new UnsignedField
<1>(this, (unsigned int &)mix
.carryTrim
));
991 internalField
.Append(new UnsignedField
<2>(this, mix
.mixWarn
));
992 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
993 internalField
.Append(new SpareBitsField
<1>(this));
994 internalField
.Append(new SignedField
<14>(this, _offset
));
995 internalField
.Append(new SwitchField
<9>(this, mix
.swtch
, board
, version
));
996 internalField
.Append(new UnsignedField
<9>(this, mix
.flightModes
));
997 internalField
.Append(new CurveReferenceField(this, mix
.curve
, board
, version
));
998 internalField
.Append(new UnsignedField
<8>(this, mix
.delayUp
));
999 internalField
.Append(new UnsignedField
<8>(this, mix
.delayDown
));
1000 internalField
.Append(new UnsignedField
<8>(this, mix
.speedUp
));
1001 internalField
.Append(new UnsignedField
<8>(this, mix
.speedDown
));
1002 if (IS_HORUS(board
))
1003 internalField
.Append(new ZCharField
<6>(this, mix
.name
));
1004 else if (HAS_LARGE_LCD(board
))
1005 internalField
.Append(new ZCharField
<8>(this, mix
.name
));
1007 internalField
.Append(new ZCharField
<6>(this, mix
.name
));
1009 else if (IS_TARANIS(board
) && version
== 217) {
1010 internalField
.Append(new UnsignedField
<8>(this, _destCh
));
1011 internalField
.Append(new UnsignedField
<9>(this, mix
.flightModes
));
1012 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1013 internalField
.Append(new UnsignedField
<1>(this, (unsigned int &)mix
.carryTrim
));
1014 internalField
.Append(new UnsignedField
<4>(this, mix
.mixWarn
));
1015 internalField
.Append(new SignedField
<16>(this, _weight
));
1016 internalField
.Append(new SourceField
<10>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1017 internalField
.Append(new SignedField
<14>(this, _offset
));
1018 internalField
.Append(new SwitchField
<8>(this, mix
.swtch
, board
, version
));
1019 internalField
.Append(new CurveReferenceField(this, mix
.curve
, board
, version
));
1020 internalField
.Append(new UnsignedField
<8>(this, mix
.delayUp
));
1021 internalField
.Append(new UnsignedField
<8>(this, mix
.delayDown
));
1022 internalField
.Append(new UnsignedField
<8>(this, mix
.speedUp
));
1023 internalField
.Append(new UnsignedField
<8>(this, mix
.speedDown
));
1024 internalField
.Append(new ZCharField
<8>(this, mix
.name
));
1026 else if (IS_ARM(board
) && version
== 217) {
1027 internalField
.Append(new UnsignedField
<5>(this, _destCh
));
1028 internalField
.Append(new UnsignedField
<3>(this, mix
.mixWarn
));
1029 internalField
.Append(new UnsignedField
<9>(this, mix
.flightModes
));
1030 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1031 internalField
.Append(new BoolField
<1>(this, mix
.noExpo
));
1032 internalField
.Append(new SignedField
<3>(this, mix
.carryTrim
));
1033 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1034 internalField
.Append(new SignedField
<16>(this, _weight
));
1035 internalField
.Append(new SwitchField
<8>(this, mix
.swtch
, board
, version
));
1036 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1037 internalField
.Append(new UnsignedField
<8>(this, mix
.delayUp
));
1038 internalField
.Append(new UnsignedField
<8>(this, mix
.delayDown
));
1039 internalField
.Append(new UnsignedField
<8>(this, mix
.speedUp
));
1040 internalField
.Append(new UnsignedField
<8>(this, mix
.speedDown
));
1041 internalField
.Append(new SourceField
<8>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1042 internalField
.Append(new SignedField
<16>(this, _offset
));
1043 internalField
.Append(new ZCharField
<6>(this, mix
.name
));
1045 else if (IS_TARANIS(board
) && version
== 216) {
1046 internalField
.Append(new UnsignedField
<8>(this, _destCh
));
1047 internalField
.Append(new UnsignedField
<16>(this, mix
.flightModes
));
1048 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1049 internalField
.Append(new UnsignedField
<1>(this, (unsigned int &)mix
.carryTrim
));
1050 internalField
.Append(new SpareBitsField
<5>(this));
1051 internalField
.Append(new SignedField
<16>(this, _weight
));
1052 internalField
.Append(new SwitchField
<8>(this, mix
.swtch
, board
, version
));
1053 internalField
.Append(new CurveReferenceField(this, mix
.curve
, board
, version
));
1054 internalField
.Append(new UnsignedField
<4>(this, mix
.mixWarn
));
1055 internalField
.Append(new SpareBitsField
<4>(this));
1056 internalField
.Append(new UnsignedField
<8>(this, mix
.delayUp
));
1057 internalField
.Append(new UnsignedField
<8>(this, mix
.delayDown
));
1058 internalField
.Append(new UnsignedField
<8>(this, mix
.speedUp
));
1059 internalField
.Append(new UnsignedField
<8>(this, mix
.speedDown
));
1060 internalField
.Append(new SourceField
<8>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1061 internalField
.Append(new SignedField
<16>(this, _offset
));
1062 internalField
.Append(new ZCharField
<8>(this, mix
.name
));
1063 internalField
.Append(new SpareBitsField
<8>(this));
1065 else if (IS_ARM(board
) && version
== 216) {
1066 internalField
.Append(new UnsignedField
<5>(this, _destCh
));
1067 internalField
.Append(new UnsignedField
<3>(this, mix
.mixWarn
));
1068 internalField
.Append(new UnsignedField
<16>(this, mix
.flightModes
));
1069 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1070 internalField
.Append(new BoolField
<1>(this, mix
.noExpo
));
1071 internalField
.Append(new SignedField
<3>(this, mix
.carryTrim
));
1072 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1073 internalField
.Append(new SpareBitsField
<1>(this));
1074 internalField
.Append(new SignedField
<16>(this, _weight
));
1075 internalField
.Append(new SwitchField
<8>(this, mix
.swtch
, board
, version
));
1076 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1077 internalField
.Append(new UnsignedField
<8>(this, mix
.delayUp
));
1078 internalField
.Append(new UnsignedField
<8>(this, mix
.delayDown
));
1079 internalField
.Append(new UnsignedField
<8>(this, mix
.speedUp
));
1080 internalField
.Append(new UnsignedField
<8>(this, mix
.speedDown
));
1081 internalField
.Append(new SourceField
<8>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1082 internalField
.Append(new SignedField
<16>(this, _offset
));
1083 internalField
.Append(new ZCharField
<6>(this, mix
.name
));
1085 else if (IS_ARM(board
)) {
1086 internalField
.Append(new UnsignedField
<8>(this, _destCh
));
1087 internalField
.Append(new UnsignedField
<16>(this, mix
.flightModes
));
1088 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1089 internalField
.Append(new BoolField
<1>(this, mix
.noExpo
));
1090 internalField
.Append(new SignedField
<3>(this, mix
.carryTrim
));
1091 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1093 internalField
.Append(new SpareBitsField
<1>(this));
1095 internalField
.Append(new UnsignedField
<1>(this, _offsetMode
));
1096 internalField
.Append(new SignedField
<16>(this, _weight
));
1097 internalField
.Append(new SwitchField
<8>(this, mix
.swtch
, board
, version
));
1098 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1099 if (version
>= 214) {
1100 internalField
.Append(new UnsignedField
<4>(this, mix
.mixWarn
));
1101 internalField
.Append(new SpareBitsField
<4>(this));
1104 internalField
.Append(new UnsignedField
<8>(this, mix
.mixWarn
));
1106 internalField
.Append(new UnsignedField
<8>(this, mix
.delayUp
));
1107 internalField
.Append(new UnsignedField
<8>(this, mix
.delayDown
));
1108 internalField
.Append(new UnsignedField
<8>(this, mix
.speedUp
));
1109 internalField
.Append(new UnsignedField
<8>(this, mix
.speedDown
));
1110 internalField
.Append(new SourceField
<8>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1112 internalField
.Append(new SignedField
<16>(this, _offset
));
1114 internalField
.Append(new SignedField
<8>(this, _offset
));
1115 if (HAS_LARGE_LCD(board
)) {
1116 internalField
.Append(new ZCharField
<8>(this, mix
.name
));
1117 internalField
.Append(new SpareBitsField
<16>(this));
1120 internalField
.Append(new ZCharField
<6>(this, mix
.name
));
1123 else if (IS_DBLRAM(board
, version
) && IS_AFTER_RELEASE_23_MARCH_2013(board
, version
)) {
1124 internalField
.Append(new UnsignedField
<4>(this, _destCh
));
1125 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1126 internalField
.Append(new BoolField
<1>(this, mix
.noExpo
));
1127 internalField
.Append(new UnsignedField
<1>(this, _weightMode
));
1128 internalField
.Append(new UnsignedField
<1>(this, _offsetMode
));
1129 internalField
.Append(new SourceField
<8>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1130 internalField
.Append(new SignedField
<8>(this, _weight
));
1131 internalField
.Append(new SwitchField
<8>(this, mix
.swtch
, board
, version
));
1132 internalField
.Append(new UnsignedField
<8>(this, mix
.flightModes
));
1133 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1134 internalField
.Append(new SignedField
<3>(this, mix
.carryTrim
));
1135 internalField
.Append(new UnsignedField
<2>(this, mix
.mixWarn
));
1136 internalField
.Append(new SpareBitsField
<1>(this));
1137 internalField
.Append(new UnsignedField
<4>(this, mix
.delayUp
));
1138 internalField
.Append(new UnsignedField
<4>(this, mix
.delayDown
));
1139 internalField
.Append(new UnsignedField
<4>(this, mix
.speedUp
));
1140 internalField
.Append(new UnsignedField
<4>(this, mix
.speedDown
));
1141 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1142 internalField
.Append(new SignedField
<8>(this, _offset
));
1145 internalField
.Append(new UnsignedField
<4>(this, _destCh
));
1146 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1147 internalField
.Append(new BoolField
<1>(this, mix
.noExpo
));
1148 internalField
.Append(new UnsignedField
<1>(this, _weightMode
));
1149 internalField
.Append(new UnsignedField
<1>(this, _offsetMode
));
1150 internalField
.Append(new SignedField
<8>(this, _weight
));
1151 internalField
.Append(new SwitchField
<6>(this, mix
.swtch
, board
, version
));
1152 internalField
.Append(new UnsignedField
<2>(this, (unsigned int &)mix
.mltpx
));
1153 internalField
.Append(new UnsignedField
<5>(this, mix
.flightModes
));
1154 internalField
.Append(new SignedField
<3>(this, mix
.carryTrim
));
1155 internalField
.Append(new SourceField
<6>(this, mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1156 internalField
.Append(new UnsignedField
<2>(this, mix
.mixWarn
));
1157 internalField
.Append(new UnsignedField
<4>(this, mix
.delayUp
));
1158 internalField
.Append(new UnsignedField
<4>(this, mix
.delayDown
));
1159 internalField
.Append(new UnsignedField
<4>(this, mix
.speedUp
));
1160 internalField
.Append(new UnsignedField
<4>(this, mix
.speedDown
));
1161 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1162 internalField
.Append(new SignedField
<8>(this, _offset
));
1166 virtual void beforeExport()
1168 if (mix
.destCh
&& mix
.srcRaw
.type
!= SOURCE_TYPE_NONE
) {
1169 _destCh
= mix
.destCh
- 1;
1170 if (mix
.curve
.type
== CurveReference::CURVE_REF_CUSTOM
) {
1172 if (mix
.curve
.value
> 0) {
1173 _curveParam
= 6 + mix
.curve
.value
;
1176 _curveParam
= mix
.curve
.value
;
1179 else if (mix
.curve
.type
== CurveReference::CURVE_REF_FUNC
) {
1181 _curveParam
= mix
.curve
.value
;
1183 else if (mix
.curve
.type
== CurveReference::CURVE_REF_DIFF
) {
1185 _curveParam
= smallGvarImport(mix
.curve
.value
);
1195 if (IS_ARM(board
)) {
1196 exportGvarParam(mix
.weight
, _weight
, version
);
1198 exportGvarParam(mix
.sOffset
, _offset
, version
);
1200 splitGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1203 splitGvarParam(mix
.weight
, _weight
, _weightMode
, board
, version
);
1204 splitGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1208 virtual void afterImport()
1210 if (IS_TARANIS(board
) && version
< 216) {
1211 if (mix
.srcRaw
.type
== SOURCE_TYPE_STICK
&& mix
.srcRaw
.index
< CPN_MAX_STICKS
) {
1213 mix
.srcRaw
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, mix
.srcRaw
.index
);
1218 if (mix
.srcRaw
.type
!= SOURCE_TYPE_NONE
) {
1219 mix
.destCh
= _destCh
+ 1;
1220 if (!IS_ARM(board
) || (!IS_STM32(board
) && version
< 218) || version
< 216) {
1222 mix
.curve
= CurveReference(CurveReference::CURVE_REF_DIFF
, smallGvarExport(_curveParam
));
1223 else if (_curveParam
> 6)
1224 mix
.curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, _curveParam
-6);
1225 else if (_curveParam
< 0)
1226 mix
.curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, _curveParam
);
1228 mix
.curve
= CurveReference(CurveReference::CURVE_REF_FUNC
, _curveParam
);
1232 if (IS_ARM(board
)) {
1233 importGvarParam(mix
.weight
, _weight
, version
);
1235 importGvarParam(mix
.sOffset
, _offset
, version
);
1237 concatGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1240 concatGvarParam(mix
.weight
, _weight
, _weightMode
, board
, version
);
1241 concatGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1244 if (IS_TARANIS(board
) && version
< 216) {
1245 if (mix
.sOffset
>= -500 && mix
.sOffset
<= 500 && mix
.weight
>= -500 && mix
.weight
<= 500) {
1246 mix
.sOffset
= divRoundClosest(mix
.sOffset
* mix
.weight
, 100);
1248 if (mix
.carryTrim
< 0) mix
.carryTrim
= 0;
1250 qCDebug(eepromImport
) << QString("imported %1: ch %2, name '%3'").arg(internalField
.getName()).arg(mix
.destCh
).arg(mix
.name
);
1254 StructField internalField
;
1257 unsigned int version
;
1259 unsigned int _destCh
;
1264 unsigned int _weightMode
;
1265 unsigned int _offsetMode
;
1268 class InputField
: public TransformedField
{
1270 InputField(DataField
* parent
, ExpoData
& expo
, Board::Type board
, unsigned int version
):
1271 TransformedField(parent
, internalField
),
1272 internalField(this, "Input"),
1277 if (IS_ARM(board
) && version
>= 218) {
1278 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
, "Mode"));
1279 internalField
.Append(new UnsignedField
<14>(this, expo
.scale
, "Scale"));
1280 internalField
.Append(new SourceField
<10>(this, expo
.srcRaw
, board
, version
, 0));
1281 internalField
.Append(new SignedField
<6>(this, expo
.carryTrim
, "CarryTrim"));
1282 internalField
.Append(new UnsignedField
<5>(this, expo
.chn
, "Channel"));
1283 internalField
.Append(new SwitchField
<9>(this, expo
.swtch
, board
, version
));
1284 internalField
.Append(new UnsignedField
<9>(this, expo
.flightModes
));
1285 internalField
.Append(new SignedField
<8>(this, _weight
, "Weight"));
1286 internalField
.Append(new SpareBitsField
<1>(this));
1287 if (IS_HORUS(board
))
1288 internalField
.Append(new ZCharField
<6>(this, expo
.name
));
1289 else if (HAS_LARGE_LCD(board
))
1290 internalField
.Append(new ZCharField
<8>(this, expo
.name
));
1292 internalField
.Append(new ZCharField
<6>(this, expo
.name
));
1293 internalField
.Append(new SignedField
<8>(this, _offset
, "Offset"));
1294 internalField
.Append(new CurveReferenceField(this, expo
.curve
, board
, version
));
1296 else if (IS_TARANIS(board
) && version
>= 217) {
1297 internalField
.Append(new SourceField
<10>(this, expo
.srcRaw
, board
, version
, 0));
1298 internalField
.Append(new UnsignedField
<14>(this, expo
.scale
, "Scale"));
1299 internalField
.Append(new UnsignedField
<8>(this, expo
.chn
, "Channel"));
1300 internalField
.Append(new SwitchField
<8>(this, expo
.swtch
, board
, version
));
1301 internalField
.Append(new UnsignedField
<16>(this, expo
.flightModes
));
1302 internalField
.Append(new SignedField
<8>(this, _weight
, "Weight"));
1303 internalField
.Append(new SignedField
<6>(this, expo
.carryTrim
, "CarryTrim"));
1304 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
, "Mode"));
1305 internalField
.Append(new ZCharField
<8>(this, expo
.name
));
1306 internalField
.Append(new SignedField
<8>(this, _offset
, "Offset"));
1307 internalField
.Append(new CurveReferenceField(this, expo
.curve
, board
, version
));
1309 else if (IS_ARM(board
) && version
>= 217) {
1310 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
, "Mode"));
1311 internalField
.Append(new UnsignedField
<3>(this, expo
.chn
, "Channel"));
1312 internalField
.Append(new BoolField
<2>(this, _curveMode
));
1313 internalField
.Append(new UnsignedField
<9>(this, expo
.flightModes
, "Phases"));
1314 internalField
.Append(new SwitchField
<8>(this, expo
.swtch
, board
, version
));
1315 internalField
.Append(new SignedField
<8>(this, _weight
, "Weight"));
1316 internalField
.Append(new ZCharField
<6>(this, expo
.name
));
1317 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1319 else if (IS_TARANIS(board
) && version
>= 216) {
1320 internalField
.Append(new SourceField
<8>(this, expo
.srcRaw
, board
, version
, 0));
1321 internalField
.Append(new UnsignedField
<16>(this, expo
.scale
, "Scale"));
1322 internalField
.Append(new UnsignedField
<8>(this, expo
.chn
, "Channel"));
1323 internalField
.Append(new SwitchField
<8>(this, expo
.swtch
, board
, version
));
1324 internalField
.Append(new UnsignedField
<16>(this, expo
.flightModes
));
1325 internalField
.Append(new SignedField
<8>(this, _weight
, "Weight"));
1326 internalField
.Append(new SignedField
<6>(this, expo
.carryTrim
, "CarryTrim"));
1327 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
, "Mode"));
1328 internalField
.Append(new ZCharField
<8>(this, expo
.name
));
1329 internalField
.Append(new SignedField
<8>(this, _offset
, "Offset"));
1330 internalField
.Append(new CurveReferenceField(this, expo
.curve
, board
, version
));
1331 internalField
.Append(new SpareBitsField
<8>(this));
1333 else if (IS_ARM(board
) && version
>= 216) {
1334 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
, "Mode"));
1335 internalField
.Append(new UnsignedField
<4>(this, expo
.chn
, "Channel"));
1336 internalField
.Append(new BoolField
<2>(this, _curveMode
));
1337 internalField
.Append(new SwitchField
<8>(this, expo
.swtch
, board
, version
));
1338 internalField
.Append(new UnsignedField
<16>(this, expo
.flightModes
, "Phases"));
1339 internalField
.Append(new SignedField
<8>(this, _weight
, "Weight"));
1340 internalField
.Append(new ZCharField
<6>(this, expo
.name
));
1341 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1343 else if (IS_ARM(board
)) {
1344 internalField
.Append(new UnsignedField
<8>(this, expo
.mode
, "Mode"));
1345 internalField
.Append(new UnsignedField
<8>(this, expo
.chn
, "Channel"));
1346 internalField
.Append(new SwitchField
<8>(this, expo
.swtch
, board
, version
));
1347 internalField
.Append(new UnsignedField
<16>(this, expo
.flightModes
, "Phases"));
1348 internalField
.Append(new SignedField
<8>(this, _weight
, "Weight"));
1349 internalField
.Append(new BoolField
<8>(this, _curveMode
));
1350 if (HAS_LARGE_LCD(board
)) {
1351 internalField
.Append(new ZCharField
<8>(this, expo
.name
));
1352 internalField
.Append(new SpareBitsField
<16>(this));
1355 internalField
.Append(new ZCharField
<6>(this, expo
.name
));
1357 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1359 else if (IS_DBLRAM(board
, version
) && IS_AFTER_RELEASE_23_MARCH_2013(board
, version
)) {
1360 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
));
1361 internalField
.Append(new UnsignedField
<2>(this, expo
.chn
));
1362 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1363 internalField
.Append(new SpareBitsField
<3>(this));
1364 internalField
.Append(new UnsignedField
<8>(this, expo
.flightModes
));
1365 internalField
.Append(new SwitchField
<8>(this, expo
.swtch
, board
, version
));
1366 internalField
.Append(new SignedField
<8>(this, _weight
));
1367 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1370 internalField
.Append(new UnsignedField
<2>(this, expo
.mode
));
1371 internalField
.Append(new SwitchField
<6>(this, expo
.swtch
, board
, version
));
1372 internalField
.Append(new UnsignedField
<2>(this, expo
.chn
));
1373 internalField
.Append(new UnsignedField
<5>(this, expo
.flightModes
));
1374 internalField
.Append(new BoolField
<1>(this, _curveMode
));
1375 internalField
.Append(new SignedField
<8>(this, _weight
));
1376 internalField
.Append(new SignedField
<8>(this, _curveParam
));
1380 virtual void beforeExport()
1382 _weight
= smallGvarImport(expo
.weight
);
1384 if ((IS_HORUS_OR_TARANIS(board
) && version
>= 216) || (IS_ARM(board
) && version
>= 218)) {
1385 _offset
= smallGvarImport(expo
.offset
);
1388 if (!IS_ARM(board
) || (!IS_TARANIS(board
) && version
< 218) || version
< 216) {
1389 if (expo
.curve
.type
==CurveReference::CURVE_REF_FUNC
&& expo
.curve
.value
) {
1391 _curveParam
= expo
.curve
.value
;
1393 else if (expo
.curve
.type
==CurveReference::CURVE_REF_CUSTOM
&& expo
.curve
.value
) {
1395 _curveParam
= expo
.curve
.value
+6;
1399 _curveParam
= smallGvarImport(expo
.curve
.value
);
1404 virtual void afterImport()
1406 if ((IS_STM32(board
) && version
< 216 )|| (!IS_STM32(board
) && expo
.mode
)) {
1407 expo
.srcRaw
= RawSource(SOURCE_TYPE_STICK
, expo
.chn
);
1410 expo
.weight
= smallGvarExport(_weight
);
1412 if ((IS_STM32(board
) && version
>= 216) || (IS_ARM(board
) && version
>= 218)) {
1413 expo
.offset
= smallGvarExport(_offset
);
1416 if (!IS_ARM(board
) || (!IS_TARANIS(board
) && version
< 218) || version
< 216) {
1418 expo
.curve
= CurveReference(CurveReference::CURVE_REF_EXPO
, smallGvarExport(_curveParam
));
1419 else if (_curveParam
> 6)
1420 expo
.curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, _curveParam
-6);
1422 expo
.curve
= CurveReference(CurveReference::CURVE_REF_FUNC
, _curveParam
);
1424 qCDebug(eepromImport
) << QString("imported %1: ch %2 name '%3'").arg(internalField
.getName()).arg(expo
.chn
).arg(expo
.name
);
1428 StructField internalField
;
1431 unsigned int version
;
1438 class LimitField
: public StructField
{
1440 template <int shift
, int GV1
>
1441 static int exportLimitValue(int value
)
1443 if (value
> 10000) {
1444 return -GV1
+ value
- 10001;
1446 if (value
< -10000) {
1447 return GV1
+ value
+ 10000;
1449 return value
+ shift
;
1452 template <int shift
, int GV1
>
1453 static int importLimitValue(int value
)
1456 return 10001 + value
- GV1
;
1458 if (value
>= GV1
-9) {
1459 return -10000 + value
- GV1
;
1462 return -10000 + value
+ GV1
+ 1;
1464 if (value
< -GV1
+9) {
1465 return 10000 + value
+ GV1
+ 1;
1467 return value
- shift
;
1470 LimitField(DataField
* parent
, LimitData
& limit
, Board::Type board
, unsigned int version
):
1471 StructField(parent
, "Limit")
1473 if (IS_ARM(board
) && version
>= 218) {
1474 Append(new ConversionField
< SignedField
<11> >(this, limit
.min
, exportLimitValue
<1000, 1024>, importLimitValue
<1000, 1024>));
1475 Append(new ConversionField
< SignedField
<11> >(this, limit
.max
, exportLimitValue
<-1000, 1024>, importLimitValue
<-1000, 1024>));
1476 Append(new SignedField
<10>(this, limit
.ppmCenter
));
1477 Append(new ConversionField
< SignedField
<11> >(this, limit
.offset
, exportLimitValue
<0, 1024>, importLimitValue
<0, 1024>));
1478 Append(new BoolField
<1>(this, limit
.symetrical
));
1479 Append(new BoolField
<1>(this, limit
.revert
));
1480 Append(new SpareBitsField
<3>(this));
1481 Append(new SignedField
<8>(this, limit
.curve
.value
));
1482 if (HAS_LARGE_LCD(board
))
1483 Append(new ZCharField
<6>(this, limit
.name
));
1485 Append(new ZCharField
<4>(this, limit
.name
));
1487 else if (IS_TARANIS(board
) && version
>= 217) {
1488 Append(new ConversionField
< SignedField
<11> >(this, limit
.min
, exportLimitValue
<1000, 1024>, importLimitValue
<1000, 1024>));
1489 Append(new ConversionField
< SignedField
<11> >(this, limit
.max
, exportLimitValue
<-1000, 1024>, importLimitValue
<-1000, 1024>));
1490 Append(new SignedField
<10>(this, limit
.ppmCenter
));
1491 Append(new ConversionField
< SignedField
<11> >(this, limit
.offset
, exportLimitValue
<0, 1024>, importLimitValue
<0, 1024>));
1492 Append(new BoolField
<1>(this, limit
.symetrical
));
1493 Append(new BoolField
<1>(this, limit
.revert
));
1494 Append(new SpareBitsField
<3>(this));
1495 Append(new SignedField
<8>(this, limit
.curve
.value
));
1496 Append(new ZCharField
<6>(this, limit
.name
));
1499 if (IS_TARANIS(board
) && version
>= 216) {
1500 Append(new ConversionField
< SignedField
<16> >(this, limit
.min
, exportLimitValue
<1000, 4096>, importLimitValue
<1000, 4096>));
1501 Append(new ConversionField
< SignedField
<16> >(this, limit
.max
, exportLimitValue
<-1000, 4096>, importLimitValue
<-1000, 4096>));
1502 Append(new SignedField
<8>(this, limit
.ppmCenter
));
1503 Append(new ConversionField
< SignedField
<14> >(this, limit
.offset
, exportLimitValue
<0, 4096>, importLimitValue
<0, 4096>));
1506 Append(new ConversionField
< SignedField
<8> >(this, limit
.min
, +100, 10));
1507 Append(new ConversionField
< SignedField
<8> >(this, limit
.max
, -100, 10));
1508 Append(new SignedField
<8>(this, limit
.ppmCenter
));
1509 Append(new SignedField
<14>(this, limit
.offset
));
1511 Append(new BoolField
<1>(this, limit
.symetrical
));
1512 Append(new BoolField
<1>(this, limit
.revert
));
1513 if (HAS_LARGE_LCD(board
)) {
1514 Append(new ZCharField
<6>(this, limit
.name
));
1516 if (IS_TARANIS(board
) && version
>= 216) {
1517 Append(new SignedField
<8>(this, limit
.curve
.value
));
1523 class CurvesField
: public TransformedField
{
1525 CurvesField(DataField
* parent
, CurveData
* curves
, Board::Type board
, unsigned int version
):
1526 TransformedField(parent
, internalField
),
1527 internalField(this, "Curves"),
1531 maxCurves(MAX_CURVES(board
, version
)),
1532 maxPoints(IS_ARM(board
) ? 512 : 112-8)
1534 for (int i
=0; i
<maxCurves
; i
++) {
1535 if (IS_ARM(board
) && version
>= 218) {
1536 internalField
.Append(new UnsignedField
<1>(this, (unsigned int &)curves
[i
].type
));
1537 internalField
.Append(new BoolField
<1>(this, curves
[i
].smooth
));
1538 internalField
.Append(new ConversionField
< SignedField
<6> >(this, curves
[i
].count
, -5));
1539 internalField
.Append(new ZCharField
<3>(this, curves
[i
].name
));
1541 else if (IS_TARANIS(board
) && version
>= 216) {
1542 internalField
.Append(new UnsignedField
<3>(this, (unsigned int &)curves
[i
].type
));
1543 internalField
.Append(new BoolField
<1>(this, curves
[i
].smooth
));
1544 internalField
.Append(new SpareBitsField
<4>(this));
1545 internalField
.Append(new ConversionField
< SignedField
<8> >(this, curves
[i
].count
, -5));
1547 else if (IS_ARM(board
)) {
1548 internalField
.Append(new SignedField
<16>(this, _curves
[i
]));
1551 internalField
.Append(new SignedField
<8>(this, _curves
[i
]));
1555 for (int i
=0; i
<maxPoints
; i
++) {
1556 internalField
.Append(new SignedField
<8>(this, _points
[i
]));
1560 virtual void beforeExport()
1562 memset(_points
, 0, sizeof(_points
));
1564 int * cur
= &_points
[0];
1567 for (int i
=0; i
<maxCurves
; i
++) {
1568 CurveData
*curve
= &curves
[i
];
1569 if (IS_STM32(board
) && version
>= 216) {
1570 offset
+= (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
? curve
->count
* 2 - 2 : curve
->count
);
1571 if (offset
> maxPoints
) {
1572 setError(QObject::tr("OpenTX only accepts %1 points in all curves").arg(maxPoints
));
1577 offset
+= (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
? curve
->count
* 2 - 2 : curve
->count
) - 5;
1578 if (offset
> maxPoints
- 5 * maxCurves
) {
1579 setError(QObject::tr("OpenTx only accepts %1 points in all curves").arg(maxPoints
));
1582 _curves
[i
] = offset
;
1584 for (int j
=0; j
<curve
->count
; j
++) {
1585 *cur
++ = curve
->points
[j
].y
;
1587 if (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
) {
1588 for (int j
=1; j
<curve
->count
-1; j
++) {
1589 *cur
++ = curve
->points
[j
].x
;
1595 virtual void afterImport()
1597 int * cur
= &_points
[0];
1599 for (int i
=0; i
<maxCurves
; i
++) {
1600 CurveData
* curve
= &curves
[i
];
1601 if (!IS_ARM(board
) || (!IS_STM32(board
) && version
< 218) || version
< 216) {
1602 int * next
= &_points
[5*(i
+1) + _curves
[i
]];
1603 int size
= next
- cur
;
1604 if (size
% 2 == 0) {
1605 curve
->count
= (size
/ 2) + 1;
1606 curve
->type
= CurveData::CURVE_TYPE_CUSTOM
;
1609 curve
->count
= size
;
1610 curve
->type
= CurveData::CURVE_TYPE_STANDARD
;
1614 if (curve
->count
> 17) {
1615 qDebug() << "Wrong points count" << curve
->count
;
1617 for (int j
=0; j
<maxCurves
; j
++) {
1618 CurveData
*curve
= &curves
[j
];
1624 for (int j
=0; j
<curve
->count
; j
++) {
1625 curve
->points
[j
].y
= *cur
++;
1628 if (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
) {
1629 curve
->points
[0].x
= -100;
1630 for (int j
=1; j
<curve
->count
-1; j
++)
1631 curve
->points
[j
].x
= *cur
++;
1632 curve
->points
[curve
->count
-1].x
= +100;
1635 for (int j
=0; j
<curve
->count
; j
++)
1636 curve
->points
[j
].x
= -100 + (200*i
) / (curve
->count
-1);
1638 qCDebug(eepromImport
) << QString("imported curve: %3 points").arg(curve
->count
);
1643 StructField internalField
;
1646 unsigned int version
;
1649 int _curves
[CPN_MAX_CURVES
];
1650 int _points
[CPN_MAX_CURVES
*CPN_MAX_POINTS
*2];
1653 class LogicalSwitchesFunctionsTable
: public ConversionTable
{
1656 LogicalSwitchesFunctionsTable(Board::Type board
, unsigned int version
)
1659 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
1660 addConversion(LS_FN_OFF
, val
++);
1661 if (IS_ARM(board
) && version
>= 216)
1662 addConversion(LS_FN_VEQUAL
, val
++);
1663 if (afterrelease21March2013
)
1664 addConversion(LS_FN_VALMOSTEQUAL
, val
++);
1665 addConversion(LS_FN_VPOS
, val
++);
1666 addConversion(LS_FN_VNEG
, val
++);
1667 if (IS_ARM(board
) && version
>= 216) val
++; // later RANGE
1668 addConversion(LS_FN_APOS
, val
++);
1669 addConversion(LS_FN_ANEG
, val
++);
1670 addConversion(LS_FN_AND
, val
++);
1671 addConversion(LS_FN_OR
, val
++);
1672 addConversion(LS_FN_XOR
, val
++);
1673 if (IS_ARM(board
) && version
>= 216) addConversion(LS_FN_EDGE
, val
++);
1674 addConversion(LS_FN_EQUAL
, val
++);
1675 if (!afterrelease21March2013
)
1676 addConversion(LS_FN_NEQUAL
, val
++);
1677 addConversion(LS_FN_GREATER
, val
++);
1678 addConversion(LS_FN_LESS
, val
++);
1679 if (!afterrelease21March2013
) {
1680 addConversion(LS_FN_EGREATER
, val
++);
1681 addConversion(LS_FN_ELESS
, val
++);
1683 addConversion(LS_FN_DPOS
, val
++);
1684 addConversion(LS_FN_DAPOS
, val
++);
1685 addConversion(LS_FN_TIMER
, val
++);
1687 addConversion(LS_FN_STICKY
, val
++);
1691 class AndSwitchesConversionTable
: public ConversionTable
{
1694 AndSwitchesConversionTable(Board::Type board
, unsigned int version
)
1697 addConversion(RawSwitch(SWITCH_TYPE_NONE
), val
++);
1699 if (IS_STM32(board
)) {
1700 for (int i
=1; i
<=MAX_SWITCHES_POSITION(board
, version
); i
++) {
1701 int s
= switchIndex(i
, board
, version
);
1702 if (IS_TARANIS(board
) && version
< 217) {
1703 // SF positions 16 and 17 => 16 and 18
1704 // SH positions 21 and 22 => 22 and 24
1705 if (s
== 17 || s
== 23) {
1709 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
);
1710 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
1712 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
1713 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, -i
), -val
);
1714 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
1717 else if (IS_SKY9X(board
)) {
1718 for (int i
=1; i
<=8; i
++) {
1719 int s
= switchIndex(i
, board
, version
);
1720 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
);
1721 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
1723 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
1724 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, -i
), -val
);
1725 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
1729 for (int i
=1; i
<=9; i
++) {
1730 int s
= switchIndex(i
, board
, version
);
1731 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
1733 for (int i
=1; i
<=7; i
++) {
1734 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
1739 static ConversionTable
* getInstance(Board::Type board
, unsigned int version
)
1741 if (IS_ARM(board
) && version
>= 216)
1742 return new SwitchesConversionTable(board
, version
);
1744 return new AndSwitchesConversionTable(board
, version
);
1747 static std::list
<Cache
> internalCache
;
1749 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
1750 Cache element
= *it
;
1751 if (element
.board
== board
&& element
.version
== version
&& element
.flags
== flags
)
1752 return element
.table
;
1755 Cache
element(board
, version
, flags
, new SwitchesConversionTable(board
, version
, flags
));
1756 internalCache
.push_back(element
);
1757 return element
.table
;
1764 void addConversion(const RawSwitch
& sw
, const int b
)
1766 ConversionTable::addConversion(sw
.toValue(), b
);
1770 class LogicalSwitchField
: public TransformedField
{
1772 LogicalSwitchField(DataField
* parent
, LogicalSwitchData
& csw
, Board::Type board
, unsigned int version
, unsigned int variant
, ModelData
* model
=NULL
):
1773 TransformedField(parent
, internalField
),
1774 internalField(this, "LogicalSwitch"),
1780 functionsConversionTable(board
, version
),
1781 sourcesConversionTable(SourcesConversionTable::getInstance(board
, version
, variant
, (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) ? 0 : FLAG_NOSWITCHES
)),
1782 switchesConversionTable(SwitchesConversionTable::getInstance(board
, version
)),
1783 andswitchesConversionTable(AndSwitchesConversionTable::getInstance(board
, version
)),
1788 if (IS_ARM(board
) && version
>= 218) {
1789 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1790 internalField
.Append(new SignedField
<10>(this, v1
));
1791 internalField
.Append(new SignedField
<10>(this, v3
));
1792 internalField
.Append(new ConversionField
< SignedField
<9> >(this, (int &)csw
.andsw
, andswitchesConversionTable
, "AND switch"));
1793 internalField
.Append(new SpareBitsField
<1>(this)); // TODO extra switch mode
1794 internalField
.Append(new SpareBitsField
<2>(this));
1795 internalField
.Append(new SignedField
<16>(this, v2
));
1797 else if (IS_ARM(board
) && version
>= 217) {
1798 internalField
.Append(new ConversionField
< UnsignedField
<6> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1799 internalField
.Append(new SignedField
<10>(this, v1
));
1800 internalField
.Append(new SignedField
<16>(this, v2
));
1801 internalField
.Append(new SignedField
<16>(this, v3
));
1803 else if (IS_ARM(board
) && version
>= 216) {
1804 internalField
.Append(new SignedField
<8>(this, v1
));
1805 internalField
.Append(new SignedField
<16>(this, v2
));
1806 internalField
.Append(new SignedField
<16>(this, v3
));
1807 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1809 else if (IS_ARM(board
) && version
>= 215) {
1810 internalField
.Append(new SignedField
<16>(this, v1
));
1811 internalField
.Append(new SignedField
<16>(this, v2
));
1812 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1814 else if (IS_ARM(board
)) {
1815 internalField
.Append(new SignedField
<8>(this, v1
));
1816 internalField
.Append(new SignedField
<8>(this, v2
));
1817 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1820 internalField
.Append(new SignedField
<8>(this, v1
));
1821 internalField
.Append(new SignedField
<8>(this, v2
));
1823 internalField
.Append(new ConversionField
< UnsignedField
<4> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1825 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.func
, &functionsConversionTable
, "Function"));
1828 if (IS_ARM(board
)) {
1829 int scale
= (version
>= 216 ? 0 : 5);
1830 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.delay
, 0, scale
));
1831 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, csw
.duration
, 0, scale
));
1832 if (version
>= 214 && version
<= 217) {
1833 internalField
.Append(new ConversionField
< SignedField
<8> >(this, (int &)csw
.andsw
, andswitchesConversionTable
, "AND switch"));
1837 if (version
>= 213) {
1838 internalField
.Append(new ConversionField
< UnsignedField
<4> >(this, (unsigned int &)csw
.andsw
, andswitchesConversionTable
, "AND switch"));
1843 ~LogicalSwitchField()
1845 delete andswitchesConversionTable
;
1848 virtual void beforeExport()
1850 if (csw
.func
== LS_FN_TIMER
) {
1854 else if (csw
.func
== LS_FN_EDGE
) {
1855 switchesConversionTable
->exportValue(csw
.val1
, v1
);
1859 else if ((csw
.func
>= LS_FN_AND
&& csw
.func
<= LS_FN_XOR
) || csw
.func
== LS_FN_STICKY
) {
1860 switchesConversionTable
->exportValue(csw
.val1
, v1
);
1861 switchesConversionTable
->exportValue(csw
.val2
, v2
);
1863 else if (csw
.func
>= LS_FN_EQUAL
&& csw
.func
<= LS_FN_ELESS
) {
1864 sourcesConversionTable
->exportValue(csw
.val1
, v1
);
1865 sourcesConversionTable
->exportValue(csw
.val2
, v2
);
1867 else if (csw
.func
!= LS_FN_OFF
) {
1868 sourcesConversionTable
->exportValue(csw
.val1
, v1
);
1873 virtual void afterImport()
1875 if (csw
.func
== LS_FN_TIMER
) {
1879 else if (csw
.func
== LS_FN_EDGE
) {
1880 switchesConversionTable
->importValue(v1
, csw
.val1
);
1884 else if ((csw
.func
>= LS_FN_AND
&& csw
.func
<= LS_FN_XOR
) || csw
.func
== LS_FN_STICKY
) {
1885 switchesConversionTable
->importValue(v1
, csw
.val1
);
1886 switchesConversionTable
->importValue(v2
, csw
.val2
);
1888 else if (csw
.func
>= LS_FN_EQUAL
&& csw
.func
<= LS_FN_ELESS
) {
1889 if (IS_ARM(board
)) {
1890 sourcesConversionTable
->importValue((uint32_t)v1
, csw
.val1
);
1891 sourcesConversionTable
->importValue((uint32_t)v2
, csw
.val2
);
1894 sourcesConversionTable
->importValue((uint8_t)v1
, csw
.val1
);
1895 sourcesConversionTable
->importValue((uint8_t)v2
, csw
.val2
);
1897 if (IS_TARANIS(board
) && version
< 216) {
1898 RawSource
val1(csw
.val1
);
1899 if (val1
.type
== SOURCE_TYPE_STICK
&& val1
.index
< CPN_MAX_STICKS
) {
1900 csw
.val1
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, val1
.index
).toValue();
1902 RawSource
val2(csw
.val2
);
1903 if (val2
.type
== SOURCE_TYPE_STICK
&& val2
.index
< CPN_MAX_STICKS
) {
1904 csw
.val2
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, val2
.index
).toValue();
1908 else if (csw
.func
!= LS_FN_OFF
) {
1909 if (IS_ARM(board
) && version
>= 217) {
1910 sourcesConversionTable
->importValue((uint32_t)v1
, csw
.val1
);
1913 sourcesConversionTable
->importValue((uint8_t)v1
, csw
.val1
);
1915 if (IS_TARANIS(board
) && version
< 216) {
1916 RawSource
val1(csw
.val1
);
1917 if (val1
.type
== SOURCE_TYPE_STICK
&& val1
.index
< CPN_MAX_STICKS
) {
1918 csw
.val1
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, val1
.index
).toValue();
1922 RawSource
val1(csw
.val1
);
1923 if (IS_ARM(board
) && version
< 216 && val1
.type
== SOURCE_TYPE_TELEMETRY
) {
1924 switch (val1
.index
) {
1925 case TELEMETRY_SOURCE_TIMER1
:
1926 case TELEMETRY_SOURCE_TIMER2
:
1927 case TELEMETRY_SOURCE_TIMER3
:
1928 csw
.val2
= (csw
.val2
+ 128) * 3;
1930 case TELEMETRY_SOURCE_ALT
:
1931 case TELEMETRY_SOURCE_GPS_ALT
:
1932 case TELEMETRY_SOURCE_ALT_MIN
:
1933 case TELEMETRY_SOURCE_ALT_MAX
:
1934 csw
.val2
= (csw
.val2
+ 128) * 8 - 500;
1936 case TELEMETRY_SOURCE_RPM
:
1937 case TELEMETRY_SOURCE_RPM_MAX
:
1938 csw
.val2
= (csw
.val2
+ 128) * 50;
1940 case TELEMETRY_SOURCE_T1
:
1941 case TELEMETRY_SOURCE_T2
:
1942 case TELEMETRY_SOURCE_T1_MAX
:
1943 case TELEMETRY_SOURCE_T2_MAX
:
1944 csw
.val2
= (csw
.val2
+ 128) + 30;
1946 case TELEMETRY_SOURCE_CELL
:
1947 case TELEMETRY_SOURCE_HDG
:
1948 csw
.val2
= (csw
.val2
+ 128) * 2;
1950 case TELEMETRY_SOURCE_DIST
:
1951 case TELEMETRY_SOURCE_DIST_MAX
:
1952 csw
.val2
= (csw
.val2
+ 128) * 8;
1954 case TELEMETRY_SOURCE_CURRENT
:
1955 case TELEMETRY_SOURCE_POWER
:
1956 csw
.val2
= (csw
.val2
+ 128) * 5;
1958 case TELEMETRY_SOURCE_CONSUMPTION
:
1959 csw
.val2
= (csw
.val2
+ 128) * 20;
1967 qCDebug(eepromImport
) << QString("imported %1: %2").arg(internalField
.getName()).arg(csw
.funcToString());
1971 StructField internalField
;
1972 LogicalSwitchData
& csw
;
1974 unsigned int version
;
1975 unsigned int variant
;
1977 LogicalSwitchesFunctionsTable functionsConversionTable
;
1978 SourcesConversionTable
* sourcesConversionTable
;
1979 SwitchesConversionTable
* switchesConversionTable
;
1980 ConversionTable
* andswitchesConversionTable
;
1986 class CustomFunctionsConversionTable
: public ConversionTable
{
1989 CustomFunctionsConversionTable(Board::Type board
, unsigned int version
)
1993 if (version
>= 216) {
1994 for (int i
=0; i
<MAX_CHANNELS(board
, version
); i
++) {
1995 addConversion(i
, val
);
1999 else if (IS_ARM(board
) || version
< 213) {
2000 for (int i
=0; i
<16; i
++) {
2001 addConversion(val
, val
);
2006 for (int i
=0; i
<16; i
++) {
2007 addConversion(i
, i
/ 4);
2012 if (version
>= 216) {
2013 addConversion(FuncTrainer
, val
);
2014 addConversion(FuncTrainerRUD
, val
);
2015 addConversion(FuncTrainerELE
, val
);
2016 addConversion(FuncTrainerTHR
, val
);
2017 addConversion(FuncTrainerAIL
, val
);
2021 addConversion(FuncTrainer
, val
++);
2022 addConversion(FuncTrainerRUD
, val
++);
2023 addConversion(FuncTrainerELE
, val
++);
2024 addConversion(FuncTrainerTHR
, val
++);
2025 addConversion(FuncTrainerAIL
, val
++);
2028 addConversion(FuncInstantTrim
, val
++);
2030 if (version
>= 216) {
2031 addConversion(FuncReset
, val
++);
2032 if (IS_ARM(board
)) {
2033 addConversion(FuncSetTimer1
, val
);
2034 addConversion(FuncSetTimer2
, val
);
2035 addConversion(FuncSetTimer3
, val
);
2038 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++)
2039 addConversion(FuncAdjustGV1
+i
, val
);
2041 if (IS_ARM(board
)) {
2042 addConversion(FuncVolume
, val
++);
2043 addConversion(FuncSetFailsafeInternalModule
, val
);
2044 addConversion(FuncSetFailsafeExternalModule
, val
++);
2045 addConversion(FuncRangeCheckInternalModule
, val
);
2046 addConversion(FuncRangeCheckExternalModule
, val
++);
2047 addConversion(FuncBindInternalModule
, val
);
2048 addConversion(FuncBindExternalModule
, val
++);
2050 addConversion(FuncPlaySound
, val
++);
2051 addConversion(FuncPlayPrompt
, val
++);
2052 if (version
>= 213 && !IS_ARM(board
))
2053 addConversion(FuncPlayBoth
, val
++);
2054 addConversion(FuncPlayValue
, val
++);
2055 if (IS_ARM(board
)) {
2056 addConversion(FuncReserve
, val
++);
2057 if (IS_STM32(board
))
2058 addConversion(FuncPlayScript
, val
++);
2060 addConversion(FuncReserve
, val
++);
2061 addConversion(FuncReserve
, val
++);
2062 addConversion(FuncBackgroundMusic
, val
++);
2063 addConversion(FuncBackgroundMusicPause
, val
++);
2065 addConversion(FuncVario
, val
++);
2066 addConversion(FuncPlayHaptic
, val
++);
2067 if (IS_2560(board
) || IS_ARM(board
) )
2068 addConversion(FuncLogs
, val
++);
2069 addConversion(FuncBacklight
, val
++);
2070 if (IS_STM32(board
))
2071 addConversion(FuncScreenshot
, val
++);
2074 addConversion(FuncPlaySound
, val
++);
2075 if (!IS_HORUS_OR_TARANIS(board
))
2076 addConversion(FuncPlayHaptic
, val
++);
2077 addConversion(FuncReset
, val
++);
2078 addConversion(FuncVario
, val
++);
2079 addConversion(FuncPlayPrompt
, val
++);
2080 if (version
>= 213 && !IS_ARM(board
))
2081 addConversion(FuncPlayBoth
, val
++);
2082 addConversion(FuncPlayValue
, val
++);
2083 if (IS_2560(board
) || IS_ARM(board
) )
2084 addConversion(FuncLogs
, val
++);
2086 addConversion(FuncVolume
, val
++);
2087 addConversion(FuncBacklight
, val
++);
2088 if (IS_ARM(board
)) {
2089 addConversion(FuncBackgroundMusic
, val
++);
2090 addConversion(FuncBackgroundMusicPause
, val
++);
2092 for (int i
=0; i
<5; i
++)
2093 addConversion(FuncAdjustGV1
+i
, val
++);
2099 class SwitchesWarningField
: public TransformedField
{
2101 SwitchesWarningField(DataField
* parent
, uint64_t & sw
, Board::Type board
, unsigned int version
):
2102 TransformedField(parent
, internalField
),
2103 internalField(this, _sw
, "SwitchesWarning"),
2110 virtual void beforeExport()
2115 virtual void afterImport()
2117 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
2118 if (afterrelease21March2013
&& version
< 216) {
2121 else if (!afterrelease21March2013
) {
2122 sw
= ((_sw
& 0x30) >> 4) + ((_sw
& 0x0E) << 1) + ((_sw
& 0xC0) >> 1);
2127 qCDebug(eepromImport
) << QString("imported %1").arg(internalField
.getName());
2131 BaseUnsignedField
<uint64_t, N
> internalField
;
2135 unsigned int version
;
2138 class ArmCustomFunctionField
: public TransformedField
{
2140 ArmCustomFunctionField(DataField
* parent
, CustomFunctionData
& fn
, Board::Type board
, unsigned int version
, unsigned int variant
):
2141 TransformedField(parent
, internalField
),
2142 internalField(this, "CustomFunction"),
2147 functionsConversionTable(board
, version
),
2148 sourcesConversionTable(SourcesConversionTable::getInstance(board
, version
, variant
, version
>= 216 ? 0 : FLAG_NONONE
)),
2153 memset(_param
, 0, sizeof(_param
));
2155 if (version
>= 218) {
2156 internalField
.Append(new SwitchField
<9>(this, fn
.swtch
, board
, version
));
2157 internalField
.Append(new ConversionField
< UnsignedField
<7> >(this, _func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2160 internalField
.Append(new SwitchField
<8>(this, fn
.swtch
, board
, version
));
2161 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, _func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2164 if (IS_TARANIS(board
) && version
>= 216)
2165 internalField
.Append(new CharField
<8>(this, _param
, false));
2166 else if (IS_TARANIS(board
))
2167 internalField
.Append(new CharField
<10>(this, _param
, false));
2169 internalField
.Append(new CharField
<6>(this, _param
, false));
2171 if (version
>= 216) {
2172 internalField
.Append(new SignedField
<8>(this, _active
));
2174 else if (version
>= 214) {
2175 internalField
.Append(new UnsignedField
<2>(this, _mode
));
2176 internalField
.Append(new UnsignedField
<6>(this, (unsigned int &)_active
));
2179 internalField
.Append(new UnsignedField
<8>(this, (unsigned int &)_active
));
2180 internalField
.Append(new SpareBitsField
<8>(this));
2184 static bool hasRepeatParam(const CustomFunctionData
& fn
)
2186 return (fn
.func
== FuncPlaySound
|| fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncPlayValue
|| fn
.func
== FuncPlayHaptic
);
2189 virtual void beforeExport()
2191 if (fn
.swtch
.type
!= SWITCH_TYPE_NONE
) {
2194 if (hasRepeatParam(fn
))
2195 _active
= (version
>= 216 ? fn
.repeatParam
: (fn
.repeatParam
/5));
2197 _active
= (fn
.enabled
? 1 : 0);
2199 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2200 if (version
>= 216) {
2201 *((uint16_t *)_param
) = fn
.param
;
2202 *((uint8_t *)(_param
+3)) = fn
.func
- FuncOverrideCH1
;
2205 *((uint32_t *)_param
) = fn
.param
;
2208 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2210 *((uint8_t *)(_param
+3)) = fn
.func
- FuncTrainer
;
2212 else if (fn
.func
>= FuncSetTimer1
&& fn
.func
<= FuncSetTimer3
) {
2213 if (version
>= 216) {
2214 *((uint16_t *)_param
) = fn
.param
;
2215 *((uint8_t *)(_param
+3)) = fn
.func
- FuncSetTimer1
;
2218 else if (fn
.func
>= FuncSetFailsafeInternalModule
&& fn
.func
<= FuncSetFailsafeExternalModule
) {
2219 if (version
>= 216) {
2220 *((uint16_t *)_param
) = fn
.func
- FuncSetFailsafeInternalModule
;
2223 else if (fn
.func
>= FuncRangeCheckInternalModule
&& fn
.func
<= FuncRangeCheckExternalModule
) {
2224 if (version
>= 216) {
2225 *((uint16_t *)_param
) = fn
.func
- FuncRangeCheckInternalModule
;
2228 else if (fn
.func
>= FuncBindInternalModule
&& fn
.func
<= FuncBindExternalModule
) {
2229 if (version
>= 216) {
2230 *((uint16_t *)_param
) = fn
.func
- FuncBindInternalModule
;
2233 else if (fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncBackgroundMusic
|| fn
.func
== FuncPlayScript
) {
2234 memcpy(_param
, fn
.paramarm
, sizeof(_param
));
2236 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2237 if (version
>= 216) {
2238 *((uint8_t *)(_param
+2)) = fn
.adjustMode
;
2239 *((uint8_t *)(_param
+3)) = fn
.func
- FuncAdjustGV1
;
2241 if (fn
.adjustMode
== 1)
2242 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2243 else if (fn
.adjustMode
== 2)
2244 value
= RawSource(fn
.param
).index
;
2247 *((uint16_t *)_param
) = value
;
2249 else if (version
>= 214) {
2251 _mode
= fn
.adjustMode
;
2252 if (fn
.adjustMode
== 1)
2253 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2254 else if (fn
.adjustMode
== 2)
2255 value
= RawSource(fn
.param
).index
;
2258 *((uint32_t *)_param
) = value
;
2262 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2263 *((uint32_t *)_param
) = value
;
2266 else if (fn
.func
== FuncPlayValue
|| fn
.func
== FuncVolume
) {
2268 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2270 *((uint16_t *)_param
) = value
;
2272 *((uint32_t *)_param
) = value
;
2274 else if (fn
.func
== FuncReset
) {
2276 *((uint32_t *)_param
) = fn
.param
;
2278 *((uint32_t *)_param
) = (fn
.param
< 2 ? fn
.param
: fn
.param
-1);
2281 *((uint32_t *)_param
) = fn
.param
;
2286 virtual void afterImport()
2288 fn
.func
= (AssignFunc
)_func
;
2290 if (hasRepeatParam(fn
))
2291 fn
.repeatParam
= (version
>= 216 ? _active
: (_active
*5));
2293 fn
.enabled
= (_active
& 0x01);
2295 unsigned int value
=0, mode
=0, index
=0;
2296 if (version
>= 216) {
2297 value
= *((uint16_t *)_param
);
2298 mode
= *((uint8_t *)(_param
+2));
2299 index
= *((uint8_t *)(_param
+3));
2302 value
= *((uint32_t *)_param
);
2305 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2306 fn
.func
= AssignFunc(fn
.func
+ index
);
2307 fn
.param
= (int16_t)(uint16_t)value
;
2309 else if (fn
.func
>= FuncSetTimer1
&& fn
.func
<= FuncSetTimer3
) {
2310 fn
.func
= AssignFunc(fn
.func
+ index
);
2311 fn
.param
= (int)value
;
2313 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2314 fn
.func
= AssignFunc(fn
.func
+ index
);
2317 else if (fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncBackgroundMusic
|| fn
.func
== FuncPlayScript
) {
2318 memcpy(fn
.paramarm
, _param
, sizeof(fn
.paramarm
));
2320 else if (fn
.func
== FuncVolume
) {
2321 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2323 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2324 if (version
>= 216) {
2325 fn
.func
= AssignFunc(fn
.func
+ index
);
2326 fn
.adjustMode
= mode
;
2327 if (fn
.adjustMode
== 1)
2328 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2329 else if (fn
.adjustMode
== 2)
2330 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, value
).toValue();
2332 fn
.param
= (int16_t)value
;
2334 else if (version
>= 214) {
2335 fn
.adjustMode
= _mode
;
2336 if (fn
.adjustMode
== 1)
2337 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2338 else if (fn
.adjustMode
== 2)
2339 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, value
).toValue();
2341 fn
.param
= (int8_t)value
;
2344 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2347 else if (fn
.func
== FuncPlayValue
) {
2349 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2351 SourcesConversionTable::getInstance(board
, version
, variant
, FLAG_NONONE
|FLAG_NOSWITCHES
)->importValue(value
, (int &)fn
.param
);
2353 else if (fn
.func
== FuncReset
) {
2357 fn
.param
= (value
< 2 ? value
: value
+1);
2362 qCDebug(eepromImport
) << QString("imported %1").arg(internalField
.getName());
2366 StructField internalField
;
2367 CustomFunctionData
& fn
;
2369 unsigned int version
;
2370 unsigned int variant
;
2371 CustomFunctionsConversionTable functionsConversionTable
;
2372 SourcesConversionTable
* sourcesConversionTable
;
2379 class AvrCustomFunctionField
: public TransformedField
{
2381 AvrCustomFunctionField(DataField
* parent
, CustomFunctionData
& fn
, Board::Type board
, unsigned int version
, unsigned int variant
):
2382 TransformedField(parent
, internalField
),
2383 internalField(this, "CustomFunction"),
2388 functionsConversionTable(board
, version
),
2389 sourcesConversionTable(SourcesConversionTable::getInstance(board
, version
, variant
, version
>= 216 ? 0 : FLAG_NONONE
)),
2395 if (version
>= 217 && IS_2560(board
)) {
2396 internalField
.Append(new SwitchField
<8>(this, fn
.swtch
, board
, version
));
2397 internalField
.Append(new ConversionField
< UnsignedField
<8> >(this, (unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2398 internalField
.Append(new UnsignedField
<2>(this, fn
.adjustMode
));
2399 internalField
.Append(new UnsignedField
<4>(this, _union_param
));
2400 internalField
.Append(new UnsignedField
<1>(this, _active
));
2401 internalField
.Append(new SpareBitsField
<1>(this));
2403 else if (version
>= 216) {
2404 internalField
.Append(new SwitchField
<6>(this, fn
.swtch
, board
, version
));
2405 internalField
.Append(new ConversionField
< UnsignedField
<4> >(this, (unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2406 internalField
.Append(new UnsignedField
<5>(this, _union_param
));
2407 internalField
.Append(new UnsignedField
<1>(this, _active
));
2409 else if (version
>= 213) {
2410 internalField
.Append(new SwitchField
<8>(this, fn
.swtch
, board
, version
));
2411 internalField
.Append(new UnsignedField
<3>(this, _union_param
));
2412 internalField
.Append(new ConversionField
< UnsignedField
<5> >(this, (unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2415 internalField
.Append(new SwitchField
<8>(this, fn
.swtch
, board
, version
));
2416 internalField
.Append(new ConversionField
< UnsignedField
<7> >(this, (unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2417 internalField
.Append(new BoolField
<1>(this, (bool &)fn
.enabled
));
2419 internalField
.Append(new UnsignedField
<8>(this, _param
));
2422 virtual void beforeExport()
2425 _active
= (fn
.enabled
? 1 : 0);
2427 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2429 _union_param
= fn
.func
- FuncOverrideCH1
;
2430 else if (version
>= 213)
2431 _active
+= ((fn
.func
% 4) << 1);
2433 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2435 _union_param
= fn
.func
- FuncTrainer
;
2437 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2438 if (version
>= 217 && IS_2560(board
)) {
2439 _union_param
= (fn
.func
- FuncAdjustGV1
);
2440 if (fn
.adjustMode
== 1)
2441 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2442 else if (fn
.adjustMode
== 2)
2443 _param
= RawSource(fn
.param
).index
;
2445 else if (version
>= 216) {
2446 _union_param
= fn
.adjustMode
;
2447 _union_param
+= (fn
.func
- FuncAdjustGV1
) << 2;
2448 if (fn
.adjustMode
== 1)
2449 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2450 else if (fn
.adjustMode
== 2)
2451 _param
= RawSource(fn
.param
).index
;
2453 else if (version
>= 213) {
2454 _active
+= (fn
.adjustMode
<< 1);
2455 if (fn
.adjustMode
== 1)
2456 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2457 else if (fn
.adjustMode
== 2)
2458 _param
= RawSource(fn
.param
).index
;
2461 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2464 else if (fn
.func
== FuncPlayValue
) {
2465 if (version
>= 216) {
2466 _union_param
= fn
.repeatParam
/ 10;
2467 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2469 else if (version
>= 213) {
2470 _active
= fn
.repeatParam
/ 10;
2471 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2474 SourcesConversionTable::getInstance(board
, version
, variant
, FLAG_NONONE
|FLAG_NOSWITCHES
)->exportValue(fn
.param
, (int &)_param
);
2477 else if (fn
.func
== FuncPlaySound
|| fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncPlayBoth
) {
2478 if (version
>= 216) {
2479 _union_param
= fn
.repeatParam
/ 10;
2481 else if (version
>= 213) {
2482 _active
= fn
.repeatParam
/ 10;
2487 virtual void afterImport()
2490 if (version
>= 213) {
2491 fn
.enabled
= (_active
& 0x01);
2494 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2496 fn
.func
= AssignFunc(fn
.func
+ _union_param
);
2497 else if (version
>= 213)
2498 fn
.func
= AssignFunc(((fn
.func
>> 2) << 2) + ((_active
>> 1) & 0x03));
2499 fn
.param
= (int8_t)fn
.param
;
2501 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2503 fn
.func
= AssignFunc(fn
.func
+ _union_param
);
2505 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2506 if (version
>= 217 && IS_2560(board
)) {
2507 fn
.func
= AssignFunc(fn
.func
+ _union_param
);
2508 if (fn
.adjustMode
== 1)
2509 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2510 else if (fn
.adjustMode
== 2)
2511 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, _param
).toValue();
2513 else if (version
>= 216) {
2514 fn
.func
= AssignFunc(fn
.func
+ (_union_param
>> 2));
2515 fn
.adjustMode
= (_union_param
& 0x03);
2516 if (fn
.adjustMode
== 1)
2517 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2518 else if (fn
.adjustMode
== 2)
2519 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, _param
).toValue();
2521 else if (version
>= 213) {
2522 fn
.adjustMode
= ((_active
>> 1) & 0x03);
2523 if (fn
.adjustMode
== 1)
2524 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2525 else if (fn
.adjustMode
== 2)
2526 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, _param
).toValue();
2529 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2532 else if (fn
.func
== FuncPlayValue
) {
2533 if (version
>= 216) {
2534 fn
.repeatParam
= _union_param
* 10;
2535 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2537 else if (version
>= 213) {
2538 fn
.repeatParam
= _active
* 10;
2539 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2542 SourcesConversionTable::getInstance(board
, version
, variant
, FLAG_NONONE
|FLAG_NOSWITCHES
)->importValue(_param
, (int &)fn
.param
);
2545 else if (fn
.func
== FuncPlaySound
|| fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncPlayBoth
) {
2547 fn
.repeatParam
= _union_param
* 10;
2548 else if (version
>= 213)
2549 fn
.repeatParam
= _active
* 10;
2551 qCDebug(eepromImport
) << QString("imported %1").arg(internalField
.getName());
2555 StructField internalField
;
2556 CustomFunctionData
& fn
;
2558 unsigned int version
;
2559 unsigned int variant
;
2560 CustomFunctionsConversionTable functionsConversionTable
;
2561 SourcesConversionTable
* sourcesConversionTable
;
2562 unsigned int _param
;
2564 unsigned int _union_param
;
2565 unsigned int _active
;
2568 class FrskyScreenField
: public DataField
{
2570 FrskyScreenField(DataField
* parent
, FrSkyScreenData
& screen
, Board::Type board
, unsigned int version
, unsigned int variant
):
2571 DataField(parent
, "Frsky Screen"),
2580 for (int i
=0; i
<4; i
++) {
2581 if (IS_ARM(board
) && version
>= 217) {
2582 if (IS_TARANIS(board
))
2583 bars
.Append(new SourceField
<16>(this, screen
.body
.bars
[i
].source
, board
, version
, variant
));
2585 bars
.Append(new SourceField
<8>(this, screen
.body
.bars
[i
].source
, board
, version
, variant
));
2586 bars
.Append(new SignedField
<16>(this, screen
.body
.bars
[i
].barMin
));
2587 bars
.Append(new SignedField
<16>(this, screen
.body
.bars
[i
].barMax
));
2590 bars
.Append(new TelemetrySourceField
<8>(this, screen
.body
.bars
[i
].source
, board
, version
));
2591 bars
.Append(new UnsignedField
<8>(this, (unsigned &)screen
.body
.bars
[i
].barMin
));
2592 bars
.Append(new UnsignedField
<8>(this, (unsigned &)screen
.body
.bars
[i
].barMax
));
2596 int columns
= (HAS_LARGE_LCD(board
) ? 3 : 2);
2597 for (int i
=0; i
<4; i
++) {
2598 for (int j
=0; j
<columns
; j
++) {
2599 if (IS_TARANIS(board
) && version
>= 217)
2600 numbers
.Append(new SourceField
<16>(this, screen
.body
.lines
[i
].source
[j
], board
, version
, variant
));
2601 else if (IS_ARM(board
) && version
>= 217)
2602 numbers
.Append(new SourceField
<8>(this, screen
.body
.lines
[i
].source
[j
], board
, version
, variant
));
2604 numbers
.Append(new TelemetrySourceField
<8>(this, screen
.body
.lines
[i
].source
[j
], board
, version
));
2607 for (unsigned i
=numbers
.size(); i
<bars
.size(); i
++) {
2608 numbers
.Append(new SpareBitsField
<1>(this));
2611 if (IS_TARANIS(board
) && version
>= 217) {
2612 script
.Append(new CharField
<8>(this, screen
.body
.script
.filename
, true, "Script name"));
2613 script
.Append(new SpareBitsField
<16*8>(this));
2616 if (IS_ARM(board
) && version
>= 217) {
2617 if (IS_TARANIS(board
))
2618 none
.Append(new SpareBitsField
<24*8>(this));
2620 none
.Append(new SpareBitsField
<20*8>(this));
2624 virtual void ExportBits(QBitArray
& output
)
2626 if (IS_ARM(board
) && version
>= 217) {
2627 if (screen
.type
== TELEMETRY_SCREEN_SCRIPT
)
2628 script
.ExportBits(output
);
2629 else if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2630 numbers
.ExportBits(output
);
2631 else if (screen
.type
== TELEMETRY_SCREEN_BARS
)
2632 bars
.ExportBits(output
);
2634 none
.ExportBits(output
);
2637 if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2638 numbers
.ExportBits(output
);
2640 bars
.ExportBits(output
);
2644 virtual void ImportBits(const QBitArray
& input
)
2646 qCDebug(eepromImport
) << QString("importing %1: type: %2").arg(name
).arg(screen
.type
);
2648 // NOTA: screen.type should have been imported first!
2649 if (IS_ARM(board
) && version
>= 217) {
2650 if (screen
.type
== TELEMETRY_SCREEN_SCRIPT
)
2651 script
.ImportBits(input
);
2652 else if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2653 numbers
.ImportBits(input
);
2654 else if (screen
.type
== TELEMETRY_SCREEN_BARS
)
2655 bars
.ImportBits(input
);
2657 none
.ImportBits(input
);
2660 if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2661 numbers
.ImportBits(input
);
2663 bars
.ImportBits(input
);
2667 virtual unsigned int size()
2669 // NOTA: screen.type should have been imported first!
2670 if (IS_ARM(board
) && version
>= 217) {
2671 if (screen
.type
== TELEMETRY_SCREEN_SCRIPT
)
2672 return script
.size();
2673 else if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2674 return numbers
.size();
2675 else if (screen
.type
== TELEMETRY_SCREEN_BARS
)
2681 if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2682 return numbers
.size();
2689 FrSkyScreenData
& screen
;
2691 unsigned int version
;
2694 StructField numbers
;
2698 class RSSIConversionTable
: public ConversionTable
2701 RSSIConversionTable(int index
)
2703 addConversion(0, 2-index
);
2704 addConversion(1, 3-index
);
2705 addConversion(2, index
? 3 : 0);
2706 addConversion(3, 1-index
);
2709 RSSIConversionTable()
2714 class TelemetryVarioSourceConversionTable
: public ConversionTable
2717 TelemetryVarioSourceConversionTable(Board::Type board
, unsigned int version
)
2720 if (!IS_HORUS_OR_TARANIS(board
)) {
2721 addConversion(TELEMETRY_VARIO_SOURCE_ALTI
, val
++);
2722 addConversion(TELEMETRY_VARIO_SOURCE_ALTI_PLUS
, val
++);
2724 addConversion(TELEMETRY_VARIO_SOURCE_VSPEED
, val
++);
2725 addConversion(TELEMETRY_VARIO_SOURCE_A1
, val
++);
2726 addConversion(TELEMETRY_VARIO_SOURCE_A2
, val
++);
2727 if (IS_HORUS_OR_TARANIS(board
)) {
2728 addConversion(TELEMETRY_VARIO_SOURCE_DTE
, val
++);
2733 class TelemetryVoltsSourceConversionTable
: public ConversionTable
2736 TelemetryVoltsSourceConversionTable(Board::Type board
, unsigned int version
)
2739 addConversion(TELEMETRY_VOLTS_SOURCE_A1
, val
++);
2740 addConversion(TELEMETRY_VOLTS_SOURCE_A2
, val
++);
2741 if (IS_ARM(board
) && version
>= 216) {
2742 addConversion(TELEMETRY_VOLTS_SOURCE_A3
, val
++);
2743 addConversion(TELEMETRY_VOLTS_SOURCE_A4
, val
++);
2745 addConversion(TELEMETRY_VOLTS_SOURCE_FAS
, val
++);
2746 addConversion(TELEMETRY_VOLTS_SOURCE_CELLS
, val
++);
2750 class ScreenTypesConversionTable
: public ConversionTable
2753 ScreenTypesConversionTable(Board::Type board
, unsigned int version
)
2756 if (IS_ARM(board
)) {
2757 addConversion(TELEMETRY_SCREEN_NONE
, val
++);
2759 addConversion(TELEMETRY_SCREEN_NUMBERS
, val
++);
2760 addConversion(TELEMETRY_SCREEN_BARS
, val
++);
2764 class TelemetryCurrentSourceConversionTable
: public ConversionTable
2767 TelemetryCurrentSourceConversionTable(Board::Type board
, unsigned int version
)
2770 addConversion(TELEMETRY_CURRENT_SOURCE_NONE
, val
++);
2771 addConversion(TELEMETRY_CURRENT_SOURCE_A1
, val
++);
2772 addConversion(TELEMETRY_CURRENT_SOURCE_A2
, val
++);
2773 if (IS_ARM(board
) && version
>= 216) {
2774 addConversion(TELEMETRY_CURRENT_SOURCE_A3
, val
++);
2775 addConversion(TELEMETRY_CURRENT_SOURCE_A4
, val
++);
2777 addConversion(TELEMETRY_CURRENT_SOURCE_FAS
, val
++);
2781 class FrskyField
: public StructField
{
2783 FrskyField(DataField
* parent
, FrSkyData
& frsky
, RSSIAlarmData
& rssiAlarms
, Board::Type board
, unsigned int version
, unsigned int variant
):
2784 StructField(parent
, "FrSky"),
2785 telemetryVarioSourceConversionTable(board
, version
),
2786 screenTypesConversionTable(board
, version
),
2787 telemetryVoltsSourceConversionTable(board
, version
),
2788 telemetryCurrentSourceConversionTable(board
, version
)
2790 rssiConversionTable
[0] = RSSIConversionTable(0);
2791 rssiConversionTable
[1] = RSSIConversionTable(1);
2793 if (IS_ARM(board
)) {
2794 if (!IS_HORUS(board
)) {
2795 if (version
>= 217) {
2796 Append(new UnsignedField
<8>(this, frsky
.voltsSource
, "Volts Source"));
2797 Append(new UnsignedField
<8>(this, frsky
.altitudeSource
, "Altitude Source"));
2800 for (int i
= 0; i
< (version
>= 216 ? 4 : 2); i
++) {
2801 Append(new UnsignedField
<8>(this, frsky
.channels
[i
].ratio
, "Ratio"));
2802 Append(new SignedField
<12>(this, frsky
.channels
[i
].offset
, "Offset"));
2803 Append(new UnsignedField
<4>(this, frsky
.channels
[i
].type
, "Type"));
2804 for (int j
= 0; j
< 2; j
++)
2805 Append(new UnsignedField
<8>(this, frsky
.channels
[i
].alarms
[j
].value
, "Alarm value"));
2806 for (int j
= 0; j
< 2; j
++)
2807 Append(new UnsignedField
<2>(this, frsky
.channels
[i
].alarms
[j
].level
));
2808 for (int j
= 0; j
< 2; j
++)
2809 Append(new UnsignedField
<1>(this, frsky
.channels
[i
].alarms
[j
].greater
));
2810 Append(new SpareBitsField
<2>(this));
2811 Append(new UnsignedField
<8>(this, frsky
.channels
[i
].multiplier
, 0, 5, "Multiplier"));
2813 Append(new UnsignedField
<8>(this, frsky
.usrProto
));
2814 if (version
>= 216) {
2815 Append(new ConversionField
<UnsignedField
<7> >(this, frsky
.voltsSource
, &telemetryVoltsSourceConversionTable
, "Volts Source"));
2816 Append(new SpareBitsField
<1>(this));
2819 Append(new ConversionField
<UnsignedField
<8> >(this, frsky
.voltsSource
, &telemetryVoltsSourceConversionTable
, "Volts Source"));
2821 Append(new ConversionField
<SignedField
<8> >(this, frsky
.blades
, -2));
2822 Append(new ConversionField
<UnsignedField
<8> >(this, frsky
.currentSource
, &telemetryCurrentSourceConversionTable
, "Current Source"));
2825 if (version
>= 217) {
2826 for (int i
= 0; i
< 4; i
++) {
2827 Append(new UnsignedField
<2>(this, frsky
.screens
[i
].type
));
2829 for (int i
= 0; i
< 4; i
++) {
2830 Append(new FrskyScreenField(this, frsky
.screens
[i
], board
, version
, variant
));
2834 Append(new UnsignedField
<1>(this, frsky
.screens
[0].type
));
2835 Append(new UnsignedField
<1>(this, frsky
.screens
[1].type
));
2836 Append(new UnsignedField
<1>(this, frsky
.screens
[2].type
));
2837 Append(new SpareBitsField
<5>(this));
2838 for (int i
= 0; i
< 3; i
++) {
2839 Append(new FrskyScreenField(this, frsky
.screens
[i
], board
, version
, variant
));
2844 if (version
>= 217) {
2845 Append(new UnsignedField
<7>(this, frsky
.varioSource
, "Vario Source"));
2846 Append(new BoolField
<1>(this, frsky
.varioCenterSilent
));
2849 Append(new ConversionField
< UnsignedField
<8> >(this, frsky
.varioSource
, &telemetryVarioSourceConversionTable
, "Vario Source"));
2851 Append(new SignedField
<8>(this, frsky
.varioCenterMax
));
2852 Append(new SignedField
<8>(this, frsky
.varioCenterMin
));
2853 Append(new SignedField
<8>(this, frsky
.varioMin
));
2854 Append(new SignedField
<8>(this, frsky
.varioMax
));
2855 Append(new BoolField
<1>(this, rssiAlarms
.disabled
));
2856 Append(new SpareBitsField
<1>(this));
2857 Append(new ConversionField
<SignedField
<6> >(this, rssiAlarms
.warning
, -45));
2858 Append(new SpareBitsField
<2>(this));
2859 Append(new ConversionField
<SignedField
<6> >(this, rssiAlarms
.critical
, -42));
2861 if (version
== 216) {
2862 Append(new BoolField
<1>(this, frsky
.mAhPersistent
));
2863 Append(new UnsignedField
<15>(this, frsky
.storedMah
));
2864 Append(new SignedField
<8>(this, frsky
.fasOffset
));
2868 for (int i
=0; i
<2; i
++) {
2869 Append(new UnsignedField
<8>(this, frsky
.channels
[i
].ratio
, "Ratio"));
2870 Append(new SignedField
<12>(this, frsky
.channels
[i
].offset
, "Offset"));
2871 Append(new UnsignedField
<4>(this, frsky
.channels
[i
].type
, "Type"));
2872 for (int j
=0; j
<2; j
++)
2873 Append(new UnsignedField
<8>(this, frsky
.channels
[i
].alarms
[j
].value
, "Alarm value"));
2874 for (int j
=0; j
<2; j
++)
2875 Append(new UnsignedField
<2>(this, frsky
.channels
[i
].alarms
[j
].level
));
2876 for (int j
=0; j
<2; j
++)
2877 Append(new UnsignedField
<1>(this, frsky
.channels
[i
].alarms
[j
].greater
));
2878 Append(new UnsignedField
<2>(this, frsky
.channels
[i
].multiplier
, 0, 3, "Multiplier"));
2880 Append(new UnsignedField
<2>(this, frsky
.usrProto
, "USR Proto"));
2881 Append(new ConversionField
< UnsignedField
<2> >(this, (unsigned int &)frsky
.blades
, -2));
2882 for (int i
=0; i
<2; i
++) {
2883 Append(new ConversionField
< UnsignedField
<1> >(this, frsky
.screens
[i
].type
, &screenTypesConversionTable
, "Screen Type"));
2885 Append(new ConversionField
< UnsignedField
<2> >(this, frsky
.voltsSource
, &telemetryVoltsSourceConversionTable
, "Volts Source"));
2886 Append(new SignedField
<4>(this, frsky
.varioMin
, "Vario Min"));
2887 Append(new SignedField
<4>(this, frsky
.varioMax
));
2888 for (int i
=0; i
<2; i
++) {
2889 Append(new ConversionField
< UnsignedField
<2> >(this, rssiAlarms
.level
[i
], &rssiConversionTable
[i
], "RSSI level"));
2890 Append(new ConversionField
< SignedField
<6> >(this, i
==0 ? rssiAlarms
.warning
: rssiAlarms
.critical
, -45+i
*3, 0, 0, 100, "RSSI value"));
2892 for (int i
=0; i
<2; i
++) {
2893 Append(new FrskyScreenField(this, frsky
.screens
[i
], board
, version
, variant
));
2895 Append(new UnsignedField
<3>(this, frsky
.varioSource
));
2896 Append(new SignedField
<5>(this, frsky
.varioCenterMin
));
2897 Append(new ConversionField
< UnsignedField
<3> >(this, frsky
.currentSource
, &telemetryCurrentSourceConversionTable
, "Current Source"));
2898 Append(new SignedField
<5>(this, frsky
.varioCenterMax
));
2899 if (version
>= 216) {
2900 Append(new SignedField
<8>(this, frsky
.fasOffset
));
2906 RSSIConversionTable rssiConversionTable
[2];
2907 TelemetryVarioSourceConversionTable telemetryVarioSourceConversionTable
;
2908 ScreenTypesConversionTable screenTypesConversionTable
;
2909 TelemetryVoltsSourceConversionTable telemetryVoltsSourceConversionTable
;
2910 TelemetryCurrentSourceConversionTable telemetryCurrentSourceConversionTable
;
2913 class MavlinkField
: public StructField
{
2915 MavlinkField(DataField
* parent
, MavlinkData
& mavlink
, Board::Type board
, unsigned int version
):
2916 StructField(parent
, "MavLink")
2918 Append(new UnsignedField
<4>(this, mavlink
.rc_rssi_scale
, "Rc_rssi_scale"));
2919 Append(new UnsignedField
<1>(this, mavlink
.pc_rssi_en
, "Pc_rssi_en"));
2920 Append(new SpareBitsField
<3>(this));
2921 Append(new SpareBitsField
<8>(this));
2922 Append(new SpareBitsField
<8>(this));
2923 Append(new SpareBitsField
<8>(this));
2931 class CustomScreenField
: public StructField
{
2933 CustomScreenField(CustomScreenData
& customScreen
):
2934 StructField("Custom Screen"),
2935 customScreen(customScreen
)
2940 CustomScreenData
& customScreen
;
2944 class SensorField
: public TransformedField
{
2946 SensorField(DataField
* parent
, SensorData
& sensor
, Board::Type board
, unsigned int version
):
2947 TransformedField(parent
, internalField
),
2948 internalField(this, "Sensor"),
2953 internalField
.Append(new UnsignedField
<16>(this, _id
, "id/persistentValue"));
2954 internalField
.Append(new UnsignedField
<8>(this, _instance
, "instance/formula"));
2955 internalField
.Append(new ZCharField
<4>(this, sensor
.label
));
2956 internalField
.Append(new UnsignedField
<1>(this, sensor
.type
, "type"));
2957 internalField
.Append(new UnsignedField
<5>(this, sensor
.unit
, "unit"));
2958 internalField
.Append(new UnsignedField
<2>(this, sensor
.prec
, "prec"));
2959 internalField
.Append(new BoolField
<1>(this, sensor
.autoOffset
));
2960 internalField
.Append(new BoolField
<1>(this, sensor
.filter
));
2961 internalField
.Append(new BoolField
<1>(this, sensor
.logs
));
2962 internalField
.Append(new BoolField
<1>(this, sensor
.persistent
));
2963 internalField
.Append(new BoolField
<1>(this, sensor
.onlyPositive
));
2964 internalField
.Append(new UnsignedField
<3>(this, _subid
, "subid"));
2965 internalField
.Append(new UnsignedField
<32>(this, _param
, "param"));
2968 virtual void beforeExport()
2970 if (sensor
.type
== SensorData::TELEM_TYPE_CUSTOM
) {
2972 _subid
= sensor
.subid
;
2973 _instance
= sensor
.instance
;
2974 _ratio
= sensor
.ratio
;
2975 _offset
= sensor
.offset
;
2978 _id
= sensor
.persistentValue
;
2979 _instance
= sensor
.formula
;
2980 if (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
)
2981 _param
= (sensor
.source
) + (sensor
.index
<< 8);
2982 else if (sensor
.formula
== SensorData::TELEM_FORMULA_ADD
|| sensor
.formula
== SensorData::TELEM_FORMULA_AVERAGE
|| sensor
.formula
== SensorData::TELEM_FORMULA_MULTIPLY
|| sensor
.formula
== SensorData::TELEM_FORMULA_MIN
|| sensor
.formula
== SensorData::TELEM_FORMULA_MAX
)
2983 _param
= ((uint8_t)sensor
.sources
[0]) + ((uint8_t)sensor
.sources
[1] << 8) + ((uint8_t)sensor
.sources
[2] << 16) + ((uint8_t)sensor
.sources
[3] << 24);
2984 else if (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
)
2985 _param
= (sensor
.gps
) + (sensor
.alt
<< 8);
2986 else if (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
|| sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
)
2987 _param
= (sensor
.amps
);
2991 virtual void afterImport()
2993 if (sensor
.type
== SensorData::TELEM_TYPE_CUSTOM
) {
2995 sensor
.subid
= _subid
;
2996 sensor
.instance
= _instance
;
2997 sensor
.ratio
= _ratio
;
2998 sensor
.offset
= _offset
;
3001 sensor
.persistentValue
= _id
;
3002 sensor
.formula
= _instance
;
3003 if (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
)
3004 (sensor
.source
= _sources
[0], sensor
.index
= _sources
[1]);
3005 else if (sensor
.formula
== SensorData::TELEM_FORMULA_ADD
|| sensor
.formula
== SensorData::TELEM_FORMULA_AVERAGE
|| sensor
.formula
== SensorData::TELEM_FORMULA_MULTIPLY
|| sensor
.formula
== SensorData::TELEM_FORMULA_MIN
|| sensor
.formula
== SensorData::TELEM_FORMULA_MAX
)
3006 for (int i
=0; i
<4; ++i
)
3007 sensor
.sources
[i
] = _sources
[i
];
3008 else if (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
)
3009 (sensor
.gps
= _sources
[0], sensor
.alt
= _sources
[1]);
3010 else if (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
|| sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
)
3011 sensor
.amps
= _sources
[0];
3014 if (version
< 218) {
3015 if (sensor
.unit
> SensorData::UNIT_WATTS
)
3017 if (sensor
.unit
> SensorData::UNIT_DEGREE
)
3021 qCDebug(eepromImport
) << QString("imported %1").arg(internalField
.getName());
3025 StructField internalField
;
3026 SensorData
& sensor
;
3027 unsigned int version
;
3029 unsigned int _subid
;
3030 unsigned int _instance
;
3032 unsigned int _param
;
3033 uint8_t _sources
[4];
3041 int exportPpmDelay(int delay
) { return (delay
- 300) / 50; }
3042 int importPpmDelay(int delay
) { return 300 + 50 * delay
; }
3044 OpenTxModelData::OpenTxModelData(ModelData
& modelData
, Board::Type board
, unsigned int version
, unsigned int variant
):
3045 TransformedField(NULL
, internalField
),
3046 internalField(this, "ModelData"),
3047 modelData(modelData
),
3051 protocolsConversionTable(board
)
3053 sprintf(name
, "Model %s", modelData
.name
);
3055 qCDebug(eepromImport
) << QString("OpenTxModelData::OpenTxModelData(name: %1, board: %2, ver: %3, var: %4)").arg(name
).arg(board
).arg(version
).arg(variant
);
3057 if (IS_HORUS(board
))
3058 internalField
.Append(new ZCharField
<15>(this, modelData
.name
, "Model name"));
3059 else if (HAS_LARGE_LCD(board
))
3060 internalField
.Append(new ZCharField
<12>(this, modelData
.name
, "Model name"));
3062 internalField
.Append(new ZCharField
<10>(this, modelData
.name
, "Model name"));
3064 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
3066 if (afterrelease21March2013
) {
3067 internalField
.Append(new UnsignedField
<8>(this, modelData
.moduleData
[0].modelId
));
3069 if (IS_ARM(board
) && version
>= 217) {
3070 internalField
.Append(new UnsignedField
<8>(this, modelData
.moduleData
[1].modelId
));
3073 if (HAS_LARGE_LCD(board
) && version
>= 215) {
3074 internalField
.Append(new CharField
<10>(this, modelData
.bitmap
, true, "Model bitmap"));
3077 for (int i
=0; i
<MAX_TIMERS(board
, version
); i
++) {
3078 if (IS_ARM(board
) && version
>= 218) {
3079 internalField
.Append(new SwitchField
<9>(this, modelData
.timers
[i
].mode
, board
, version
, true));
3080 internalField
.Append(new UnsignedField
<23>(this, modelData
.timers
[i
].val
));
3081 internalField
.Append(new SignedField
<24>(this, modelData
.timers
[i
].pvalue
));
3082 internalField
.Append(new UnsignedField
<2>(this, modelData
.timers
[i
].countdownBeep
));
3083 internalField
.Append(new BoolField
<1>(this, modelData
.timers
[i
].minuteBeep
));
3084 internalField
.Append(new UnsignedField
<2>(this, modelData
.timers
[i
].persistent
));
3085 internalField
.Append(new SpareBitsField
<3>(this));
3086 if (HAS_LARGE_LCD(board
))
3087 internalField
.Append(new ZCharField
<8>(this, modelData
.timers
[i
].name
, "Timer name"));
3089 internalField
.Append(new ZCharField
<3>(this, modelData
.timers
[i
].name
, "Timer name"));
3091 else if (IS_ARM(board
) && version
>= 217) {
3092 internalField
.Append(new SwitchField
<8>(this, modelData
.timers
[i
].mode
, board
, version
, true));
3093 internalField
.Append(new UnsignedField
<24>(this, modelData
.timers
[i
].val
));
3094 internalField
.Append(new SignedField
<24>(this, modelData
.timers
[i
].pvalue
));
3095 internalField
.Append(new UnsignedField
<2>(this, modelData
.timers
[i
].countdownBeep
));
3096 internalField
.Append(new BoolField
<1>(this, modelData
.timers
[i
].minuteBeep
));
3097 internalField
.Append(new UnsignedField
<2>(this, modelData
.timers
[i
].persistent
));
3098 internalField
.Append(new SpareBitsField
<3>(this));
3099 if (IS_TARANIS(board
))
3100 internalField
.Append(new ZCharField
<8>(this, modelData
.timers
[i
].name
, "Timer name"));
3102 internalField
.Append(new ZCharField
<3>(this, modelData
.timers
[i
].name
, "Timer name"));
3104 else if ((IS_ARM(board
) || IS_2560(board
)) && version
>= 216) {
3105 internalField
.Append(new SwitchField
<8>(this, modelData
.timers
[i
].mode
, board
, version
, true));
3106 internalField
.Append(new UnsignedField
<16>(this, modelData
.timers
[i
].val
));
3107 internalField
.Append(new UnsignedField
<2>(this, modelData
.timers
[i
].countdownBeep
));
3108 internalField
.Append(new BoolField
<1>(this, modelData
.timers
[i
].minuteBeep
));
3109 internalField
.Append(new UnsignedField
<2>(this, modelData
.timers
[i
].persistent
));
3110 internalField
.Append(new SpareBitsField
<3>(this));
3111 internalField
.Append(new SignedField
<16>(this, modelData
.timers
[i
].pvalue
));
3113 else if (afterrelease21March2013
) {
3114 internalField
.Append(new SwitchField
<8>(this, modelData
.timers
[i
].mode
, board
, version
, true));
3115 internalField
.Append(new UnsignedField
<12>(this, modelData
.timers
[i
].val
));
3116 internalField
.Append(new BoolField
<1>(this, (bool &)modelData
.timers
[i
].countdownBeep
));
3117 internalField
.Append(new BoolField
<1>(this, modelData
.timers
[i
].minuteBeep
));
3118 if (HAS_PERSISTENT_TIMERS(board
)) {
3119 internalField
.Append(new UnsignedField
<1>(this, modelData
.timers
[i
].persistent
));
3120 internalField
.Append(new SpareBitsField
<1>(this));
3121 internalField
.Append(new SignedField
<16>(this, modelData
.timers
[i
].pvalue
));
3124 internalField
.Append(new SpareBitsField
<2>(this));
3128 internalField
.Append(new SwitchField
<8>(this, modelData
.timers
[i
].mode
, board
, version
, true));
3129 internalField
.Append(new UnsignedField
<16>(this, modelData
.timers
[i
].val
));
3130 if (HAS_PERSISTENT_TIMERS(board
)) {
3131 internalField
.Append(new UnsignedField
<1>(this, modelData
.timers
[i
].persistent
));
3132 internalField
.Append(new SpareBitsField
<15>(this));
3138 internalField
.Append(new UnsignedField
<3>(this, modelData
.telemetryProtocol
));
3140 internalField
.Append(new ConversionField
< UnsignedField
<3> >(this, (unsigned int &)modelData
.moduleData
[0].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this telemetry protocol")));
3142 internalField
.Append(new BoolField
<1>(this, modelData
.thrTrim
));
3144 if (IS_ARM(board
) && version
>= 217) {
3145 internalField
.Append(new BoolField
<1>(this, modelData
.noGlobalFunctions
));
3146 internalField
.Append(new UnsignedField
<2>(this, modelData
.trimsDisplay
));
3147 internalField
.Append(new BoolField
<1>(this, modelData
.frsky
.ignoreSensorIds
));
3149 else if (IS_HORUS_OR_TARANIS(board
) || (IS_ARM(board
) && version
>= 216)) {
3150 internalField
.Append(new SpareBitsField
<4>(this));
3153 internalField
.Append(new ConversionField
< SignedField
<4> >(this, modelData
.moduleData
[0].channelsCount
, &channelsConversionTable
, "Channels number", ::QObject::tr("OpenTX doesn't allow this number of channels")));
3157 internalField
.Append(new SignedField
<3>(this, modelData
.trimInc
));
3159 internalField
.Append(new ConversionField
< SignedField
<3> >(this, modelData
.trimInc
, +2));
3161 internalField
.Append(new BoolField
<1>(this, modelData
.disableThrottleWarning
));
3163 if (IS_HORUS_OR_TARANIS(board
) || (IS_ARM(board
) && version
>= 216))
3164 internalField
.Append(new BoolField
<1>(this, modelData
.displayChecklist
));
3166 internalField
.Append(new BoolField
<1>(this, modelData
.moduleData
[0].ppm
.pulsePol
));
3168 internalField
.Append(new BoolField
<1>(this, modelData
.extendedLimits
));
3169 internalField
.Append(new BoolField
<1>(this, modelData
.extendedTrims
));
3170 internalField
.Append(new BoolField
<1>(this, modelData
.throttleReversed
));
3172 if (!IS_ARM(board
) || version
< 216) {
3173 internalField
.Append(new ConversionField
< SignedField
<8> >(this, modelData
.moduleData
[0].ppm
.delay
, exportPpmDelay
, importPpmDelay
));
3176 if (IS_ARM(board
) || IS_2560(board
))
3177 internalField
.Append(new UnsignedField
<16>(this, modelData
.beepANACenter
));
3179 internalField
.Append(new UnsignedField
<8>(this, modelData
.beepANACenter
));
3181 for (int i
=0; i
<MAX_MIXERS(board
, version
); i
++)
3182 internalField
.Append(new MixField(this, modelData
.mixData
[i
], board
, version
, &modelData
));
3183 for (int i
=0; i
<MAX_CHANNELS(board
, version
); i
++)
3184 internalField
.Append(new LimitField(this, modelData
.limitData
[i
], board
, version
));
3185 for (int i
=0; i
<MAX_EXPOS(board
, version
); i
++)
3186 internalField
.Append(new InputField(this, modelData
.expoData
[i
], board
, version
));
3187 internalField
.Append(new CurvesField(this, modelData
.curves
, board
, version
));
3188 for (int i
=0; i
<MAX_LOGICAL_SWITCHES(board
, version
); i
++)
3189 internalField
.Append(new LogicalSwitchField(this, modelData
.logicalSw
[i
], board
, version
, variant
, &modelData
));
3190 for (int i
=0; i
<MAX_CUSTOM_FUNCTIONS(board
, version
); i
++) {
3192 internalField
.Append(new ArmCustomFunctionField(this, modelData
.customFn
[i
], board
, version
, variant
));
3194 internalField
.Append(new AvrCustomFunctionField(this, modelData
.customFn
[i
], board
, version
, variant
));
3196 internalField
.Append(new HeliField(this, modelData
.swashRingData
, board
, version
, variant
));
3197 for (int i
=0; i
<MAX_FLIGHT_MODES(board
, version
); i
++) {
3198 internalField
.Append(new FlightModeField(this, modelData
.flightModeData
[i
], i
, board
, version
));
3201 if (!IS_ARM(board
) || version
< 216) {
3202 internalField
.Append(new SignedField
<8>(this, modelData
.moduleData
[0].ppm
.frameLength
));
3205 internalField
.Append(new UnsignedField
<8>(this, modelData
.thrTraceSrc
, "Throttle Source"));
3207 if (!afterrelease21March2013
) {
3208 internalField
.Append(new UnsignedField
<8>(this, modelData
.moduleData
[0].modelId
));
3211 if (IS_HORUS(board
))
3212 internalField
.Append(new SwitchesWarningField
<32>(this, modelData
.switchWarningStates
, board
, version
));
3213 else if (IS_TARANIS_X9E(board
))
3214 internalField
.Append(new SwitchesWarningField
<64>(this, modelData
.switchWarningStates
, board
, version
));
3215 else if (IS_TARANIS(board
))
3216 internalField
.Append(new SwitchesWarningField
<16>(this, modelData
.switchWarningStates
, board
, version
));
3218 internalField
.Append(new SwitchesWarningField
<8>(this, modelData
.switchWarningStates
, board
, version
));
3221 if (IS_TARANIS_X9E(board
))
3222 internalField
.Append(new UnsignedField
<32>(this, modelData
.switchWarningEnable
));
3223 else if (!IS_HORUS(board
) && version
>= 216)
3224 internalField
.Append(new UnsignedField
<8>(this, modelData
.switchWarningEnable
));
3226 if (board
!= BOARD_STOCK
&& (board
!= BOARD_M128
|| version
< 215)) {
3227 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
3228 if (version
>= 218) {
3229 internalField
.Append(new ZCharField
<3>(this, modelData
.gvarData
[i
].name
, "GVar name"));
3230 internalField
.Append(new SignedField
<12>(this, modelData
.gvarData
[i
].min
));
3231 internalField
.Append(new SignedField
<12>(this, modelData
.gvarData
[i
].max
));
3232 internalField
.Append(new BoolField
<1>(this, modelData
.gvarData
[i
].popup
));
3233 internalField
.Append(new UnsignedField
<1>(this, modelData
.gvarData
[i
].prec
));
3234 internalField
.Append(new UnsignedField
<2>(this, modelData
.gvarData
[i
].unit
));
3235 internalField
.Append(new SpareBitsField
<4>(this));
3238 internalField
.Append(new ZCharField
<6>(this, modelData
.gvarData
[i
].name
, "GVar name"));
3239 if (version
>= 216) {
3240 internalField
.Append(new BoolField
<1>(this, modelData
.gvarData
[i
].popup
));
3241 internalField
.Append(new SpareBitsField
<7>(this));
3246 else if (variant
& GVARS_VARIANT
) {
3247 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
3248 // on M64 GVARS are common to all flight modes, and there is no name
3249 internalField
.Append(new SignedField
<16>(this, modelData
.flightModeData
[0].gvars
[i
]));
3253 if ((board
!= BOARD_STOCK
&& (board
!= BOARD_M128
|| version
< 215)) || (variant
& FRSKY_VARIANT
)) {
3254 internalField
.Append(new FrskyField(this, modelData
.frsky
, modelData
.rssiAlarms
, board
, version
, variant
));
3256 else if ((board
== BOARD_STOCK
|| board
== BOARD_M128
) && (variant
& MAVLINK_VARIANT
)) {
3257 internalField
.Append(new MavlinkField(this, modelData
.mavlink
, board
, version
));
3260 if (IS_TARANIS(board
) && version
< 215) {
3261 internalField
.Append(new CharField
<10>(this, modelData
.bitmap
, true, "Model bitmap"));
3264 int modulesCount
= 2;
3266 if (IS_STM32(board
)) {
3268 if (version
>= 217) {
3269 internalField
.Append(new SpareBitsField
<3>(this));
3270 internalField
.Append(new UnsignedField
<3>(this, modelData
.trainerMode
));
3271 internalField
.Append(new UnsignedField
<2>(this, modelData
.potsWarningMode
));
3274 internalField
.Append(new ConversionField
< SignedField
<8> >(this, modelData
.moduleData
[1].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
3275 internalField
.Append(new UnsignedField
<8>(this, modelData
.trainerMode
));
3278 else if (IS_ARM(board
)) {
3279 if (version
>= 217) {
3281 internalField
.Append(new SpareBitsField
<6>(this));
3282 internalField
.Append(new UnsignedField
<2>(this, modelData
.potsWarningMode
));
3284 else if (version
>= 216) {
3286 internalField
.Append(new ConversionField
< SignedField
<8> >(this, modelData
.moduleData
[0].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
3290 if (IS_ARM(board
) && version
>= 215) {
3291 for (int module
=0; module
<modulesCount
; module
++) {
3292 if (version
>= 217) {
3293 internalField
.Append(new ConversionField
<SignedField
<4> >(this, modelData
.moduleData
[module
].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
3294 internalField
.Append(new SignedField
<4>(this, subprotocols
[module
]));
3297 internalField
.Append(new SignedField
<8>(this, subprotocols
[module
]));
3299 internalField
.Append(new UnsignedField
<8>(this, modelData
.moduleData
[module
].channelsStart
));
3300 internalField
.Append(new ConversionField
<SignedField
<8> >(this, modelData
.moduleData
[module
].channelsCount
, -8));
3301 if (version
>= 217) {
3302 internalField
.Append(new UnsignedField
<4>(this, modelData
.moduleData
[module
].failsafeMode
));
3303 internalField
.Append(new UnsignedField
<3>(this, modelData
.moduleData
[module
].subType
));
3304 internalField
.Append(new BoolField
<1>(this, modelData
.moduleData
[module
].invertedSerial
));
3307 internalField
.Append(new ConversionField
<UnsignedField
<8> >(this, modelData
.moduleData
[module
].failsafeMode
, -1));
3309 for (int i
=0; i
<32; i
++) {
3310 internalField
.Append(new SignedField
<16>(this, modelData
.moduleData
[module
].failsafeChannels
[i
]));
3312 if (version
>= 217) {
3313 internalField
.Append(new ConversionField
< SignedField
<6> >(this, modelData
.moduleData
[module
].ppm
.delay
, exportPpmDelay
, importPpmDelay
));
3314 internalField
.Append(new BoolField
<1>(this, modelData
.moduleData
[module
].ppm
.pulsePol
));
3315 internalField
.Append(new BoolField
<1>(this, modelData
.moduleData
[module
].ppm
.outputType
));
3316 internalField
.Append(new SignedField
<8>(this, modelData
.moduleData
[module
].ppm
.frameLength
));
3319 internalField
.Append(new ConversionField
< SignedField
<8> >(this, modelData
.moduleData
[module
].ppm
.delay
, exportPpmDelay
, importPpmDelay
));
3320 internalField
.Append(new SignedField
<8>(this, modelData
.moduleData
[module
].ppm
.frameLength
));
3321 internalField
.Append(new BoolField
<8>(this, modelData
.moduleData
[module
].ppm
.pulsePol
));
3326 if (IS_TARANIS(board
) && version
< 218) {
3327 for (int i
=0; i
<MAX_CURVES(board
, version
); i
++) {
3328 internalField
.Append(new ZCharField
<6>(this, modelData
.curves
[i
].name
, "Curve name"));
3332 if (IS_STM32(board
)) {
3333 if (version
>= 218) {
3334 for (int i
=0; i
<MAX_SCRIPTS(board
); i
++) {
3335 ScriptData
& script
= modelData
.scriptData
[i
];
3336 internalField
.Append(new CharField
<6>(this, script
.filename
, true, "Script filename"));
3337 internalField
.Append(new ZCharField
<6>(this, script
.name
, "Script name"));
3338 for (int j
=0; j
<6; j
++) {
3339 internalField
.Append(new SignedField
<16>(this, script
.inputs
[j
]));
3343 else if (version
>= 217) {
3344 for (int i
=0; i
<7; i
++) {
3345 ScriptData
& script
= modelData
.scriptData
[i
];
3346 internalField
.Append(new CharField
<8>(this, script
.filename
, true, "Script filename"));
3347 internalField
.Append(new ZCharField
<8>(this, script
.name
, "Script name"));
3348 for (int j
=0; j
<8; j
++) {
3349 internalField
.Append(new SignedField
<8>(this, script
.inputs
[j
]));
3353 else if (version
>= 216) {
3354 for (int i
=0; i
<7; i
++) {
3355 ScriptData
& script
= modelData
.scriptData
[i
];
3356 internalField
.Append(new CharField
<10>(this, script
.filename
, true, "Script filename"));
3357 internalField
.Append(new ZCharField
<10>(this, script
.name
, "Script name"));
3358 for (int j
=0; j
<10; j
++) {
3359 internalField
.Append(new SignedField
<8>(this, script
.inputs
[j
]));
3365 if (IS_ARM(board
) && version
>= 216) {
3366 for (int i
=0; i
<32; i
++) {
3367 if (HAS_LARGE_LCD(board
))
3368 internalField
.Append(new ZCharField
<4>(this, modelData
.inputNames
[i
], "Input name"));
3370 internalField
.Append(new ZCharField
<3>(this, modelData
.inputNames
[i
], "Input name"));
3374 if (IS_ARM(board
) && version
>= 217) {
3375 for (int i
=0; i
<8; i
++) {
3376 if (i
< MAX_POTS(board
, version
)+MAX_SLIDERS(board
))
3377 internalField
.Append(new BoolField
<1>(this, modelData
.potsWarningEnabled
[i
]));
3379 internalField
.Append(new SpareBitsField
<1>(this));
3382 else if (IS_ARM(board
) && version
>= 216) {
3383 for (int i
=0; i
<6; i
++) {
3384 if (i
< MAX_POTS(board
, version
)+MAX_SLIDERS(board
))
3385 internalField
.Append(new BoolField
<1>(this, modelData
.potsWarningEnabled
[i
]));
3387 internalField
.Append(new SpareBitsField
<1>(this));
3389 internalField
.Append(new UnsignedField
<2>(this, modelData
.potsWarningMode
));
3392 if (IS_ARM(board
) && version
>= 216) {
3393 for (int i
=0; i
< MAX_POTS(board
, version
)+MAX_SLIDERS(board
); i
++) {
3394 internalField
.Append(new SignedField
<8>(this, modelData
.potPosition
[i
]));
3398 if (IS_ARM(board
) && version
== 216) {
3399 internalField
.Append(new SpareBitsField
<16>(this));
3402 if (IS_SKY9X(board
) && version
>= 217) {
3403 internalField
.Append(new SpareBitsField
<8>(this));
3404 internalField
.Append(new SpareBitsField
<8>(this));
3407 if (IS_ARM(board
) && version
>= 217) {
3408 for (int i
=0; i
<MAX_TELEMETRY_SENSORS(board
, version
); ++i
) {
3409 internalField
.Append(new SensorField(this, modelData
.sensorData
[i
], board
, version
));
3413 if (IS_TARANIS_X9E(board
)) {
3414 internalField
.Append(new UnsignedField
<8>(this, modelData
.toplcdTimer
));
3417 if (IS_HORUS(board
)) {
3418 for (int i
= 0; i
< 5; i
++) {
3419 internalField
.Append(new CharField
<610>(this, modelData
.customScreenData
[i
], false, "Custom screen blob"));
3421 internalField
.Append(new CharField
<216>(this, modelData
.topbarData
, false, "Top bar blob"));
3422 internalField
.Append(new SpareBitsField
<8>(this)); // current view
3426 void OpenTxModelData::beforeExport()
3428 // qDebug() << QString("before export model") << modelData.name;
3430 for (int module
=0; module
<3; module
++) {
3431 if ((modelData
.moduleData
[module
].protocol
>= PULSES_PXX_XJT_X16
&& modelData
.moduleData
[module
].protocol
<= PULSES_PXX_XJT_LR12
) ||
3432 modelData
.moduleData
[module
].protocol
== PULSES_PXX_R9M
) {
3433 if (! (modelData
.moduleData
[module
].protocol
== PULSES_PXX_R9M
)) {
3434 subprotocols
[module
] = modelData
.moduleData
[module
].protocol
- PULSES_PXX_XJT_X16
;
3436 int pxxByte
= (modelData
.moduleData
[module
].pxx
.power
& 0x03)
3437 | modelData
.moduleData
[module
].pxx
.receiver_telem_off
<< 4
3438 | modelData
.moduleData
[module
].pxx
.receiver_channel_9_16
<< 5;
3439 modelData
.moduleData
[module
].ppm
.delay
= 300 + 50 * pxxByte
;
3440 modelData
.moduleData
[module
].ppm
.pulsePol
= modelData
.moduleData
[module
].pxx
.external_antenna
;
3441 modelData
.moduleData
[module
].ppm
.outputType
= modelData
.moduleData
[module
].pxx
.sport_out
;
3444 else if (modelData
.moduleData
[module
].protocol
>= PULSES_LP45
&& modelData
.moduleData
[module
].protocol
<= PULSES_DSMX
) {
3445 subprotocols
[module
] = modelData
.moduleData
[module
].protocol
- PULSES_LP45
;
3447 else if (modelData
.moduleData
[module
].protocol
== PULSES_MULTIMODULE
) {
3448 // copy multi settings to ppm settings to get them written to the eeprom
3449 // (reverse the int => ms logic of the ppm delay) since only ppm is written
3450 subprotocols
[module
] = modelData
.moduleData
[module
].multi
.rfProtocol
& (0x1f);
3451 int multiByte
= ((modelData
.moduleData
[module
].multi
.rfProtocol
>> 4) & 0x03) | (modelData
.moduleData
[module
].multi
.customProto
<< 7);
3452 modelData
.moduleData
[module
].ppm
.delay
= 300 + 50 * multiByte
;
3453 modelData
.moduleData
[module
].ppm
.frameLength
= modelData
.moduleData
[module
].multi
.optionValue
;
3454 modelData
.moduleData
[module
].ppm
.outputType
= modelData
.moduleData
[module
].multi
.lowPowerMode
;
3455 modelData
.moduleData
[module
].ppm
.pulsePol
= modelData
.moduleData
[module
].multi
.autoBindMode
;
3458 subprotocols
[module
] = (module
== 0 ? -1 : 0);
3462 if (IS_HORUS(board
)) {
3463 uint32_t newSwitchWarningStates
= 0;
3464 for (int i
= 0; i
< MAX_SWITCHES(board
, version
); i
++) {
3465 uint8_t value
= (modelData
.switchWarningStates
>> (2*i
)) & 0x03;
3466 if (!(modelData
.switchWarningEnable
& (1 << i
))) {
3467 newSwitchWarningStates
|= (value
+ 1) << (3*i
);
3470 modelData
.switchWarningStates
= newSwitchWarningStates
;
3474 void OpenTxModelData::afterImport()
3476 qCDebug(eepromImport
) << QString("OpenTxModelData::afterImport()") << modelData
.name
;
3478 if (IS_TARANIS(board
) && version
< 216) {
3479 for (unsigned int i
=0; i
<CPN_MAX_STICKS
; i
++) {
3480 for (int j
=0; j
<64; j
++) {
3481 ExpoData
* expo
= &modelData
.expoData
[j
];
3482 if (expo
->mode
== INPUT_MODE_BOTH
&& expo
->chn
== i
&& expo
->flightModes
== 0 && expo
->swtch
.type
== SWITCH_TYPE_NONE
)
3484 if (expo
->mode
== 0 || expo
->chn
> i
) {
3485 ExpoData
* newExpo
= modelData
.insertInput(j
);
3486 newExpo
->mode
= INPUT_MODE_BOTH
;
3487 newExpo
->srcRaw
= RawSource(SOURCE_TYPE_STICK
, i
);
3489 newExpo
->weight
= 100;
3493 strncpy(modelData
.inputNames
[i
], getCurrentFirmware()->getAnalogInputName(i
).toLatin1().constData(), sizeof(modelData
.inputNames
[i
])-1);
3497 if (IS_HORUS(board
)) {
3498 modelData
.moduleData
[0].protocol
= PULSES_PXX_XJT_X16
;
3501 for (int module
=0; module
<3; module
++) {
3502 if (modelData
.moduleData
[module
].protocol
== PULSES_PXX_XJT_X16
|| modelData
.moduleData
[module
].protocol
== PULSES_LP45
) {
3503 if (subprotocols
[module
] >= 0)
3504 modelData
.moduleData
[module
].protocol
+= subprotocols
[module
];
3506 modelData
.moduleData
[module
].protocol
= PULSES_OFF
;
3508 else if (modelData
.moduleData
[module
].protocol
== PULSES_MULTIMODULE
) {
3509 // Copy data from ppm struct to multi struct
3510 unsigned int multiByte
= (unsigned int)((modelData
.moduleData
[module
].ppm
.delay
- 300) / 50);
3511 modelData
.moduleData
[module
].multi
.rfProtocol
= (subprotocols
[module
] & 0x0f) | ((multiByte
& 0x3) << 4);
3512 modelData
.moduleData
[module
].multi
.customProto
= (multiByte
& 0x80) == 0x80;
3513 modelData
.moduleData
[module
].multi
.optionValue
= modelData
.moduleData
[module
].ppm
.frameLength
;
3514 modelData
.moduleData
[module
].multi
.lowPowerMode
= modelData
.moduleData
[module
].ppm
.outputType
;
3515 modelData
.moduleData
[module
].multi
.autoBindMode
= modelData
.moduleData
[module
].ppm
.pulsePol
;
3518 if ((modelData
.moduleData
[module
].protocol
>= PULSES_PXX_XJT_X16
&& modelData
.moduleData
[module
].protocol
<= PULSES_PXX_XJT_LR12
) ||
3519 modelData
.moduleData
[module
].protocol
== PULSES_PXX_R9M
) {
3520 // Do the same for pxx
3521 unsigned int pxxByte
= (unsigned int)((modelData
.moduleData
[module
].ppm
.delay
- 300) / 50);
3522 modelData
.moduleData
[module
].pxx
.power
= pxxByte
& 0x03;
3523 modelData
.moduleData
[module
].pxx
.receiver_telem_off
= static_cast<bool>(pxxByte
& (1 << 4));
3524 modelData
.moduleData
[module
].pxx
.receiver_channel_9_16
= static_cast<bool>(pxxByte
& (1 << 5));
3525 modelData
.moduleData
[module
].pxx
.external_antenna
= modelData
.moduleData
[module
].ppm
.outputType
;
3526 modelData
.moduleData
[module
].pxx
.sport_out
= modelData
.moduleData
[module
].ppm
.pulsePol
;
3530 if (IS_TARANIS(board
) && version
< 217 && modelData
.moduleData
[1].protocol
!= PULSES_OFF
) {
3531 modelData
.moduleData
[1].modelId
= modelData
.moduleData
[0].modelId
;
3534 if (IS_HORUS(board
)) {
3535 uint32_t newSwitchWarningStates
= 0;
3536 for (int i
= 0; i
< MAX_SWITCHES(board
, version
); i
++) {
3537 uint8_t value
= (modelData
.switchWarningStates
>> (3*i
)) & 0x07;
3539 modelData
.switchWarningEnable
|= (1 << i
);
3541 newSwitchWarningStates
|= ((value
& 0x03) - 1) << (2*i
);
3543 modelData
.switchWarningStates
= newSwitchWarningStates
;
3547 OpenTxGeneralData::OpenTxGeneralData(GeneralSettings
& generalData
, Board::Type board
, unsigned int version
, unsigned int variant
):
3548 TransformedField(NULL
, internalField
),
3549 internalField(this, "General Settings"),
3550 generalData(generalData
),
3553 inputsCount(CPN_MAX_STICKS
+MAX_POTS(board
, version
)+MAX_SLIDERS(board
)+MAX_MOUSE_ANALOGS(board
))
3555 qCDebug(eepromImport
) << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board
).arg(version
).arg(variant
);
3557 generalData
.version
= version
;
3558 generalData
.variant
= variant
;
3560 internalField
.Append(new UnsignedField
<8>(this, generalData
.version
));
3561 if (version
>= 213 || (!IS_ARM(board
) && version
>= 212))
3562 internalField
.Append(new UnsignedField
<16>(this, generalData
.variant
));
3564 if (version
>= 216) {
3565 for (int i
=0; i
<inputsCount
; i
++) {
3566 internalField
.Append(new SignedField
<16>(this, generalData
.calibMid
[i
]));
3567 internalField
.Append(new SignedField
<16>(this, generalData
.calibSpanNeg
[i
]));
3568 internalField
.Append(new SignedField
<16>(this, generalData
.calibSpanPos
[i
]));
3572 for (int i
=0; i
<inputsCount
; i
++) {
3573 if (!IS_TARANIS(board
) || i
!=6)
3574 internalField
.Append(new SignedField
<16>(this, generalData
.calibMid
[i
]));
3576 for (int i
=0; i
<inputsCount
; i
++) {
3577 if (!IS_TARANIS(board
) || i
!=6)
3578 internalField
.Append(new SignedField
<16>(this, generalData
.calibSpanNeg
[i
]));
3580 for (int i
=0; i
<inputsCount
; i
++) {
3581 if (!IS_TARANIS(board
) || i
!=6)
3582 internalField
.Append(new SignedField
<16>(this, generalData
.calibSpanPos
[i
]));
3586 internalField
.Append(new UnsignedField
<16>(this, chkSum
));
3587 if (!IS_HORUS(board
)) {
3588 internalField
.Append(new UnsignedField
<8>(this, generalData
.currModelIndex
));
3589 internalField
.Append(new UnsignedField
<8>(this, generalData
.contrast
));
3591 internalField
.Append(new UnsignedField
<8>(this, generalData
.vBatWarn
));
3592 internalField
.Append(new SignedField
<8>(this, generalData
.txVoltageCalibration
));
3593 internalField
.Append(new SignedField
<8>(this, generalData
.backlightMode
));
3595 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
3596 internalField
.Append(new SignedField
<16>(this, generalData
.trainer
.calib
[i
]));
3598 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
3599 internalField
.Append(new UnsignedField
<6>(this, generalData
.trainer
.mix
[i
].src
));
3600 internalField
.Append(new UnsignedField
<2>(this, generalData
.trainer
.mix
[i
].mode
));
3601 internalField
.Append(new SignedField
<8>(this, generalData
.trainer
.mix
[i
].weight
));
3604 internalField
.Append(new UnsignedField
<8>(this, generalData
.view
, 0, MAX_VIEWS(board
)-1));
3606 internalField
.Append(new SpareBitsField
<2>(this)); // TODO buzzerMode?
3607 internalField
.Append(new BoolField
<1>(this, generalData
.fai
));
3608 internalField
.Append(new SignedField
<2>(this, (int &)generalData
.beeperMode
));
3609 internalField
.Append(new BoolField
<1>(this, generalData
.flashBeep
));
3610 internalField
.Append(new BoolField
<1>(this, generalData
.disableMemoryWarning
));
3611 internalField
.Append(new BoolField
<1>(this, generalData
.disableAlarmWarning
));
3613 internalField
.Append(new UnsignedField
<2>(this, generalData
.stickMode
));
3614 internalField
.Append(new SignedField
<5>(this, generalData
.timezone
));
3615 if (version
>= 217 && IS_HORUS_OR_TARANIS(board
)) {
3616 internalField
.Append(new BoolField
<1>(this, generalData
.adjustRTC
));
3619 internalField
.Append(new SpareBitsField
<1>(this));
3622 internalField
.Append(new UnsignedField
<8>(this, generalData
.inactivityTimer
));
3624 if (version
>= 215) {
3625 internalField
.Append(new UnsignedField
<3>(this, generalData
.mavbaud
));
3628 internalField
.Append(new SpareBitsField
<1>(this));
3629 internalField
.Append(new BoolField
<1>(this, generalData
.minuteBeep
));
3630 internalField
.Append(new BoolField
<1>(this, generalData
.preBeep
));
3634 internalField
.Append(new SpareBitsField
<3>(this));
3636 if (version
>= 216 && IS_HORUS(board
))
3637 internalField
.Append(new SpareBitsField
<3>(this));
3638 else if (version
>= 216 && IS_TARANIS(board
))
3639 internalField
.Append(new SignedField
<3>(this, generalData
.splashDuration
));
3640 else if (version
>= 213 || (!IS_ARM(board
) && version
>= 212))
3641 internalField
.Append(new UnsignedField
<3>(this, generalData
.splashMode
)); // TODO
3643 internalField
.Append(new SpareBitsField
<3>(this));
3644 internalField
.Append(new SignedField
<2>(this, (int &)generalData
.hapticMode
));
3647 internalField
.Append(new SignedField
<8>(this, generalData
.switchesDelay
));
3649 internalField
.Append(new SpareBitsField
<8>(this)); // TODO blOffBright + blOnBright
3651 internalField
.Append(new UnsignedField
<8>(this, generalData
.backlightDelay
));
3652 internalField
.Append(new UnsignedField
<8>(this, generalData
.templateSetup
));
3653 internalField
.Append(new SignedField
<8>(this, generalData
.PPM_Multiplier
));
3654 internalField
.Append(new SignedField
<8>(this, generalData
.hapticLength
));
3656 if (version
< 216 || (version
< 218 && !IS_9X(board
)) || (!IS_9X(board
) && !IS_TARANIS(board
) && !IS_HORUS(board
))) {
3657 internalField
.Append(new UnsignedField
<8>(this, generalData
.reNavigation
));
3660 if (version
>= 216 && !IS_TARANIS(board
) && !IS_HORUS(board
)) {
3661 internalField
.Append(new UnsignedField
<8>(this, generalData
.stickReverse
));
3664 internalField
.Append(new SignedField
<3>(this, generalData
.beeperLength
));
3665 internalField
.Append(new SignedField
<3>(this, generalData
.hapticStrength
));
3666 internalField
.Append(new UnsignedField
<1>(this, generalData
.gpsFormat
));
3667 internalField
.Append(new SpareBitsField
<1>(this)); // unexpectedShutdown
3669 internalField
.Append(new UnsignedField
<8>(this, generalData
.speakerPitch
));
3672 internalField
.Append(new ConversionField
< SignedField
<8> >(this, generalData
.speakerVolume
, -12, 0, 0, 23, "Volume"));
3674 internalField
.Append(new ConversionField
< SignedField
<8> >(this, generalData
.speakerVolume
, -7, 0, 0, 7, "Volume"));
3676 if (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) {
3677 internalField
.Append(new SignedField
<8>(this, generalData
.vBatMin
));
3678 internalField
.Append(new SignedField
<8>(this, generalData
.vBatMax
));
3681 if (IS_ARM(board
)) {
3682 internalField
.Append(new UnsignedField
<8>(this, generalData
.backlightBright
));
3683 if (version
< 218) internalField
.Append(new SignedField
<8>(this, generalData
.txCurrentCalibration
));
3684 if (version
>= 213) {
3685 if (version
< 218) internalField
.Append(new SignedField
<8>(this, generalData
.temperatureWarn
));
3686 if (version
< 218) internalField
.Append(new UnsignedField
<8>(this, generalData
.mAhWarn
));
3687 if (version
< 218) internalField
.Append(new UnsignedField
<16>(this, generalData
.mAhUsed
));
3688 internalField
.Append(new UnsignedField
<32>(this, generalData
.globalTimer
));
3689 if (version
< 218) internalField
.Append(new SignedField
<8>(this, generalData
.temperatureCalib
));
3690 internalField
.Append(new UnsignedField
<4>(this, generalData
.bluetoothBaudrate
));
3691 internalField
.Append(new UnsignedField
<4>(this, generalData
.bluetoothMode
));
3692 if (version
< 218) internalField
.Append(new BoolField
<8>(this, generalData
.optrexDisplay
));
3693 if (version
< 218) internalField
.Append(new UnsignedField
<8>(this, generalData
.sticksGain
));
3695 if (version
>= 214) {
3696 if (version
< 218) internalField
.Append(new UnsignedField
<8>(this, generalData
.rotarySteps
));
3697 internalField
.Append(new UnsignedField
<8>(this, generalData
.countryCode
));
3698 internalField
.Append(new UnsignedField
<1>(this, generalData
.imperial
));
3699 if (version
>= 218) {
3700 internalField
.Append(new BoolField
<1>(this, generalData
.jitterFilter
));
3701 internalField
.Append(new BoolField
<1>(this, generalData
.disableRssiPoweroffAlarm
));
3702 internalField
.Append(new UnsignedField
<2>(this, generalData
.usbMode
));
3703 internalField
.Append(new SpareBitsField
<3>(this));
3706 internalField
.Append(new SpareBitsField
<7>(this));
3709 if (version
>= 215) {
3710 internalField
.Append(new CharField
<2>(this, generalData
.ttsLanguage
, true, "TTS language"));
3711 if (version
>= 218) {
3712 internalField
.Append(new SignedField
<4>(this, generalData
.beepVolume
));
3713 internalField
.Append(new SignedField
<4>(this, generalData
.wavVolume
));
3714 internalField
.Append(new SignedField
<4>(this, generalData
.varioVolume
));
3715 internalField
.Append(new SignedField
<4>(this, generalData
.backgroundVolume
));
3718 internalField
.Append(new SignedField
<8>(this, generalData
.beepVolume
));
3719 internalField
.Append(new SignedField
<8>(this, generalData
.wavVolume
));
3720 internalField
.Append(new SignedField
<8>(this, generalData
.varioVolume
));
3722 if (version
>= 216) {
3723 internalField
.Append(new SignedField
<8>(this, generalData
.varioPitch
));
3724 internalField
.Append(new SignedField
<8>(this, generalData
.varioRange
));
3725 internalField
.Append(new SignedField
<8>(this, generalData
.varioRepeat
));
3727 if (version
< 218) internalField
.Append(new SignedField
<8>(this, generalData
.backgroundVolume
));
3729 if (version
>= 218) {
3730 for (int i
=0; i
<MAX_CUSTOM_FUNCTIONS(board
, version
); i
++) {
3731 internalField
.Append(new ArmCustomFunctionField(this, generalData
.customFn
[i
], board
, version
, variant
));
3735 if (IS_STM32(board
) && version
>= 216) {
3736 if (version
>= 218) {
3737 internalField
.Append(new UnsignedField
<4>(this, generalData
.hw_uartMode
));
3738 for (uint8_t i
=0; i
<4; i
++) {
3739 internalField
.Append(new UnsignedField
<1>(this, generalData
.sliderConfig
[i
]));
3742 else if (version
>= 217) {
3743 internalField
.Append(new UnsignedField
<6>(this, generalData
.hw_uartMode
));
3744 if (IS_TARANIS_X9E(board
)) {
3745 internalField
.Append(new UnsignedField
<1>(this, generalData
.sliderConfig
[2]));
3746 internalField
.Append(new UnsignedField
<1>(this, generalData
.sliderConfig
[3]));
3749 internalField
.Append(new SpareBitsField
<2>(this));
3753 internalField
.Append(new UnsignedField
<8>(this, generalData
.hw_uartMode
));
3755 if (IS_HORUS(board
)) {
3756 for (int i
=0; i
<16; i
++) {
3757 if (i
< MAX_SWITCHES(board
, version
))
3758 internalField
.Append(new UnsignedField
<2>(this, generalData
.switchConfig
[i
]));
3760 internalField
.Append(new SpareBitsField
<2>(this));
3763 for (int i
=0; i
<4; i
++) {
3764 if (i
< MAX_POTS(board
, version
))
3765 internalField
.Append(new UnsignedField
<2>(this, generalData
.potConfig
[i
]));
3767 internalField
.Append(new SpareBitsField
<2>(this));
3769 if (!IS_HORUS(board
)) {
3770 internalField
.Append(new UnsignedField
<8>(this, generalData
.backlightColor
));
3773 else if (IS_SKY9X(board
) && version
>= 218) {
3774 internalField
.Append(new SignedField
<8>(this, generalData
.txCurrentCalibration
));
3775 internalField
.Append(new SignedField
<8>(this, generalData
.temperatureWarn
));
3776 internalField
.Append(new UnsignedField
<8>(this, generalData
.mAhWarn
));
3777 internalField
.Append(new UnsignedField
<16>(this, generalData
.mAhUsed
));
3778 internalField
.Append(new SignedField
<8>(this, generalData
.temperatureCalib
));
3779 internalField
.Append(new BoolField
<8>(this, generalData
.optrexDisplay
));
3780 internalField
.Append(new UnsignedField
<8>(this, generalData
.sticksGain
));
3781 internalField
.Append(new UnsignedField
<8>(this, generalData
.rotarySteps
));
3784 if (IS_TARANIS_X9E(board
))
3785 internalField
.Append(new SpareBitsField
<64>(this)); // switchUnlockStates
3786 else if (IS_TARANIS(board
))
3787 internalField
.Append(new SpareBitsField
<16>(this)); // switchUnlockStates
3789 if (version
== 217) {
3790 for (int i
=0; i
<MAX_CUSTOM_FUNCTIONS(board
, version
); i
++) {
3791 internalField
.Append(new ArmCustomFunctionField(this, generalData
.customFn
[i
], board
, version
, variant
));
3795 if (IS_HORUS(board
)) {
3796 for (int i
=0; i
<MAX_SWITCHES(board
, version
); ++i
) {
3797 internalField
.Append(new ZCharField
<3>(this, generalData
.switchName
[i
], "Switch name"));
3799 for (int i
=0; i
<CPN_MAX_STICKS
; ++i
) {
3800 internalField
.Append(new ZCharField
<3>(this, generalData
.stickName
[i
], "Stick name"));
3802 for (int i
=0; i
<MAX_POTS(board
, version
); ++i
) {
3803 internalField
.Append(new ZCharField
<3>(this, generalData
.potName
[i
], "Pot name"));
3805 for (int i
=0; i
<MAX_SLIDERS(board
); ++i
) {
3806 internalField
.Append(new ZCharField
<3>(this, generalData
.sliderName
[i
], "Slider name"));
3808 internalField
.Append(new CharField
<17>(this, generalData
.currModelFilename
, true, "Current model filename"));
3810 else if (IS_TARANIS(board
) && version
>= 217) {
3811 for (int i
=0; i
<MAX_SWITCH_SLOTS(board
, version
); i
++) {
3812 if (i
< MAX_SWITCHES(board
, version
))
3813 internalField
.Append(new UnsignedField
<2>(this, generalData
.switchConfig
[i
]));
3815 internalField
.Append(new SpareBitsField
<2>(this));
3817 for (int i
=0; i
<MAX_SWITCHES(board
, version
); ++i
) {
3818 internalField
.Append(new ZCharField
<3>(this, generalData
.switchName
[i
], "Switch name"));
3820 for (int i
=0; i
<CPN_MAX_STICKS
; ++i
) {
3821 internalField
.Append(new ZCharField
<3>(this, generalData
.stickName
[i
], "Stick name"));
3823 for (int i
=0; i
<MAX_POTS(board
, version
); ++i
) {
3824 internalField
.Append(new ZCharField
<3>(this, generalData
.potName
[i
], "Pot name"));
3826 for (int i
=0; i
<MAX_SLIDERS(board
); ++i
) {
3827 internalField
.Append(new ZCharField
<3>(this, generalData
.sliderName
[i
], "Slider name"));
3831 if (IS_HORUS(board
)) {
3832 internalField
.Append(new SpareBitsField
<1>(this));
3833 internalField
.Append(new UnsignedField
<7>(this, generalData
.backlightOffBright
));
3834 internalField
.Append(new ZCharField
<10>(this, generalData
.bluetoothName
, "Bluetooth name"));
3836 else if (IS_TARANIS_X9E(board
) && version
>= 217) {
3837 internalField
.Append(new BoolField
<8>(this, generalData
.bluetoothEnable
));
3838 internalField
.Append(new ZCharField
<10>(this, generalData
.bluetoothName
, "Bluetooth name"));
3841 if (IS_HORUS(board
)) {
3842 internalField
.Append(new CharField
<8>(this, generalData
.themeName
, true, "Theme name"));
3843 for (int i
=0; i
<5; i
++) {
3844 internalField
.Append(new CharField
<8>(this, (char *)generalData
.themeOptionValue
[i
], true, "Theme blob"));
3850 void OpenTxGeneralData::beforeExport()
3853 if (version
>= 216) {
3855 for (int i
=0; i
<inputsCount
; i
++) {
3856 sum
+= generalData
.calibMid
[i
];
3857 if (++count
== 12) break;
3858 sum
+= generalData
.calibSpanNeg
[i
];
3859 if (++count
== 12) break;
3860 sum
+= generalData
.calibSpanPos
[i
];
3861 if (++count
== 12) break;
3865 for (int i
=0; i
<inputsCount
; i
++)
3866 sum
+= generalData
.calibMid
[i
];
3867 for (int i
=0; i
<5; i
++)
3868 sum
+= generalData
.calibSpanNeg
[i
];
3873 void OpenTxGeneralData::afterImport()
3875 if (IS_TARANIS(board
) && version
< 217) {
3876 generalData
.potConfig
[0] = POT_WITH_DETENT
;
3877 generalData
.potConfig
[1] = POT_WITH_DETENT
;