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 #define IS_DBLEEPROM(board, version) ((IS_2560(board) || board==BOARD_M128) && version >= 213)
28 // Macro used for Gruvin9x board and M128 board between versions 213 and 214 (when there were stack overflows!)
29 #define IS_DBLRAM(board, version) ((IS_2560(board) && version >= 213) || (board==BOARD_M128 && version >= 213 && version <= 214))
31 #define HAS_PERSISTENT_TIMERS(board) (IS_ARM(board) || IS_2560(board))
32 #define MAX_VIEWS(board) (HAS_LARGE_LCD(board) ? 2 : 256)
33 #define MAX_POTS(board, version) (IS_HORUS(board) ? 3 : (board == BOARD_TARANIS_X7 ? 2 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 4 : (version >= 216 ? 3 : 2)) : 3)))
34 #define MAX_SLIDERS(board) (IS_HORUS(board) ? 4 : (board == BOARD_TARANIS_X7 ? 0 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 4 : 2) : 0)))
35 #define MAX_MOUSE_ANALOGS(board) (IS_HORUS(board) ? 2 : 0)
36 #define MAX_SWITCHES(board, version) (IS_HORUS(board) ? 8 : (board == BOARD_TARANIS_X7 ? 6 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 18 : 8) : 7)))
37 #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)))
38 #define MAX_ROTARY_ENCODERS(board) (IS_2560(board) ? 2 : (IS_SKY9X(board) ? 1 : 0))
39 #define MAX_FLIGHT_MODES(board, version) (IS_ARM(board) ? 9 : (IS_DBLRAM(board, version) ? 6 : 5))
40 #define MAX_TIMERS(board, version) ((IS_ARM(board) && version >= 217) ? 3 : 2)
41 #define MAX_MIXERS(board, version) (IS_ARM(board) ? 64 : 32)
42 #define MAX_CHANNELS(board, version) (IS_ARM(board) ? 32 : 16)
43 #define MAX_TRIMS(board) (IS_HORUS(board) ? 6 : 4)
44 #define MAX_EXPOS(board, version) (IS_ARM(board) ? ((IS_HORUS_OR_TARANIS(board) && version >= 216) ? 64 : 32) : (IS_DBLRAM(board, version) ? 16 : 14))
45 #define MAX_LOGICAL_SWITCHES(board, version) (IS_ARM(board) ? (version >= 218 ? 64 : 32) : ((IS_DBLEEPROM(board, version) && version<217) ? 15 : 12))
46 #define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? (version >= 216 ? 64 : 32) : (IS_DBLEEPROM(board, version) ? 24 : 16))
47 #define MAX_CURVES(board, version) (IS_ARM(board) ? ((HAS_LARGE_LCD(board) && version >= 216) ? 32 : 16) : 8)
48 #define MAX_GVARS(board, version) ((IS_ARM(board) && version >= 216) ? 9 : 5)
49 #define MAX_SCRIPTS(board) (IS_HORUS(board) ? 9 : 7)
50 #define MAX_TELEMETRY_SENSORS(board, version) (32)
51 #define NUM_PPM_INPUTS(board, version) ((IS_ARM(board) && version >= 216) ? 16 : 8)
52 #define ROTENC_COUNT(board, version) (IS_ARM(board) ? ((IS_STM32(board) && version >= 218) ? 0 : 1) : (IS_2560(board) ? 2 : 0))
53 #define MAX_AUX_TRIMS(board) (IS_HORUS(board) ? 2 : 0)
55 #define IS_AFTER_RELEASE_21_MARCH_2013(board, version) (version >= 214 || (!IS_ARM(board) && version >= 213))
56 #define IS_AFTER_RELEASE_23_MARCH_2013(board, version) (version >= 214 || (board==BOARD_STOCK && version >= 213))
58 inline int switchIndex(int i
, BoardEnum board
, unsigned int version
)
60 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
61 if (!IS_HORUS_OR_TARANIS(board
) && afterrelease21March2013
)
62 return (i
<=3 ? i
+3 : (i
<=6 ? i
-3 : i
));
67 class SwitchesConversionTable
: public ConversionTable
{
70 SwitchesConversionTable(BoardEnum board
, unsigned int version
, bool timer
=false)
76 for (int i
=0; i
<5; i
++) {
77 addConversion(RawSwitch(SWITCH_TYPE_TIMER_MODE
, i
), val
++);
81 addConversion(RawSwitch(SWITCH_TYPE_NONE
), val
++);
84 for (int i
=1; i
<=MAX_SWITCHES_POSITION(board
, version
); i
++) {
85 int s
= switchIndex(i
, board
, version
);
86 if (IS_TARANIS(board
) && version
< 217) {
87 // SF positions 16 and 17 => 16 and 18
88 // SH positions 21 and 22 => 22 and 24
89 if (s
== 17 || s
== 23) {
93 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
);
94 addImportConversion(RawSwitch(SWITCH_TYPE_SWITCH
, 21+22-s
), -val
+offset
);
95 addExportConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
+offset
);
100 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
);
101 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
+offset
);
105 if (IS_HORUS_OR_TARANIS(board
) && version
>= 216) {
106 for (int i
=1; i
<=MAX_POTS(board
, version
)*6; i
++) {
107 addConversion(RawSwitch(SWITCH_TYPE_MULTIPOS_POT
, -i
), -val
+offset
);
108 addConversion(RawSwitch(SWITCH_TYPE_MULTIPOS_POT
, i
), val
++);
112 if (version
>= 216) {
113 for (int i
=1; i
<=2*MAX_TRIMS(board
); i
++) {
114 addConversion(RawSwitch(SWITCH_TYPE_TRIM
, -i
), -val
+offset
);
115 addConversion(RawSwitch(SWITCH_TYPE_TRIM
, i
), val
++);
119 if (version
>= 216) {
120 for (int i
=1; i
<=MAX_ROTARY_ENCODERS(board
); i
++) {
121 addConversion(RawSwitch(SWITCH_TYPE_ROTARY_ENCODER
, -i
), -val
+offset
);
122 addConversion(RawSwitch(SWITCH_TYPE_ROTARY_ENCODER
, i
), val
++);
126 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
127 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, -i
), -val
+offset
);
128 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
131 addConversion(RawSwitch(SWITCH_TYPE_OFF
), -val
+offset
);
132 addConversion(RawSwitch(SWITCH_TYPE_ON
), val
++);
133 if (version
>= 216) {
134 addConversion(RawSwitch(SWITCH_TYPE_ONE
, -1), -val
+offset
);
135 addConversion(RawSwitch(SWITCH_TYPE_ONE
, 1), val
++);
137 for (int i
=1; i
<=MAX_FLIGHT_MODES(board
, version
); i
++) {
138 addConversion(RawSwitch(SWITCH_TYPE_FLIGHT_MODE
, -i
), -val
+offset
);
139 addConversion(RawSwitch(SWITCH_TYPE_FLIGHT_MODE
, i
), val
++);
145 // previous "moment" switches
146 for (int i
=1; i
<=MAX_SWITCHES_POSITION(board
, version
); i
++) {
147 int s
= switchIndex(i
, board
, version
);
148 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
151 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
152 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
155 // previous "One" switch
156 addConversion(RawSwitch(SWITCH_TYPE_ON
), val
++);
162 void addConversion(const RawSwitch
& sw
, const int b
)
164 ConversionTable::addConversion(sw
.toValue(), b
);
167 void addImportConversion(const RawSwitch
& sw
, const int b
)
169 ConversionTable::addImportConversion(sw
.toValue(), b
);
172 void addExportConversion(const RawSwitch
& sw
, const int b
)
174 ConversionTable::addExportConversion(sw
.toValue(), b
);
179 Cache(BoardEnum board
, unsigned int version
, unsigned long flags
, SwitchesConversionTable
* table
):
187 unsigned int version
;
189 SwitchesConversionTable
* table
;
192 static std::list
<Cache
> internalCache
;
196 static SwitchesConversionTable
* getInstance(BoardEnum board
, unsigned int version
, unsigned long flags
=0)
198 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
200 if (element
.board
== board
&& element
.version
== version
&& element
.flags
== flags
)
201 return element
.table
;
204 Cache
element(board
, version
, flags
, new SwitchesConversionTable(board
, version
, flags
));
205 internalCache
.push_back(element
);
206 return element
.table
;
208 static void Cleanup()
210 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
212 delete element
.table
;
214 internalCache
.clear();
218 std::list
<SwitchesConversionTable::Cache
> SwitchesConversionTable::internalCache
;
220 #define FLAG_NONONE 0x01
221 #define FLAG_NOSWITCHES 0x02
222 #define FLAG_NOTELEMETRY 0x04
224 class SourcesConversionTable
: public ConversionTable
{
227 SourcesConversionTable(BoardEnum board
, unsigned int version
, unsigned int variant
, unsigned long flags
=0)
229 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
233 if (!(flags
& FLAG_NONONE
)) {
234 addConversion(RawSource(SOURCE_TYPE_NONE
), val
++);
237 if (IS_STM32(board
) && version
>= 216) {
238 for (int i
=0; i
<32; i
++) {
239 addConversion(RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, i
), val
++);
241 for (int i
=0; i
<MAX_SCRIPTS(board
); i
++) {
242 for (int j
=0; j
<6; j
++) {
243 addConversion(RawSource(SOURCE_TYPE_LUA_OUTPUT
, i
*16+j
), val
++);
248 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_POTS(board
, version
)+MAX_SLIDERS(board
)+MAX_MOUSE_ANALOGS(board
); i
++) {
249 addConversion(RawSource(SOURCE_TYPE_STICK
, i
), val
++);
252 for (int i
=0; i
<MAX_ROTARY_ENCODERS(board
); i
++) {
253 addConversion(RawSource(SOURCE_TYPE_ROTARY_ENCODER
, 0), val
++);
256 if (!afterrelease21March2013
) {
257 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
258 addConversion(RawSource(SOURCE_TYPE_TRIM
, i
), val
++);
262 addConversion(RawSource(SOURCE_TYPE_MAX
), val
++);
264 if (afterrelease21March2013
) {
265 for (int i
=0; i
<3; i
++)
266 addConversion(RawSource(SOURCE_TYPE_CYC
, i
), val
++);
269 if (afterrelease21March2013
) {
270 for (int i
=0; i
<MAX_TRIMS(board
); i
++)
271 addConversion(RawSource(SOURCE_TYPE_TRIM
, i
), val
++);
274 addConversion(RawSource(SOURCE_TYPE_SWITCH
, 0), val
++);
276 if (!(flags
& FLAG_NOSWITCHES
)) {
277 if (afterrelease21March2013
) {
278 for (int i
=1; i
<MAX_SWITCHES(board
, version
); i
++)
279 addConversion(RawSource(SOURCE_TYPE_SWITCH
, i
), val
++);
282 for (int i
=1; i
<=9; i
++) {
284 addConversion(RawSource(SOURCE_TYPE_SWITCH
, 0), val
++);
286 addConversion(RawSource(SOURCE_TYPE_SWITCH
, i
), val
++);
289 for (int i
=0; i
<MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
290 addConversion(RawSource(SOURCE_TYPE_CUSTOM_SWITCH
, i
), val
++);
294 if (!afterrelease21March2013
) {
295 for (int i
=0; i
<3; i
++) {
296 addConversion(RawSource(SOURCE_TYPE_CYC
, i
), val
++);
300 for (int i
=0; i
<NUM_PPM_INPUTS(board
, version
); i
++) {
301 addConversion(RawSource(SOURCE_TYPE_PPM
, i
), val
++);
304 for (int i
=0; i
<MAX_CHANNELS(board
, version
); i
++) {
305 addConversion(RawSource(SOURCE_TYPE_CH
, i
), val
++);
308 if (!(flags
& FLAG_NOTELEMETRY
)) {
309 if (IS_ARM(board
) && version
>= 217) {
310 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++)
311 addConversion(RawSource(SOURCE_TYPE_GVAR
, i
), val
++);
312 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 0), val
++); // BATT
313 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 1), val
++); // TIME
315 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 2), val
++); // Timer1
316 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 3), val
++); // Timer2
317 addConversion(RawSource(SOURCE_TYPE_SPECIAL
, 4), val
++); // Timer3
318 for (int i
=0; i
<CPN_MAX_SENSORS
*3; ++i
) {
319 addConversion(RawSource(SOURCE_TYPE_TELEMETRY
, i
), val
++);
323 if (afterrelease21March2013
) {
324 if ((board
!= BOARD_STOCK
&& (board
!=BOARD_M128
|| version
<215)) || (variant
& GVARS_VARIANT
)) {
325 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
326 addConversion(RawSource(SOURCE_TYPE_GVAR
, i
), val
++);
331 for (int i
=0; i
<TELEMETRY_SOURCE_ACC
; i
++) {
333 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
)
336 if (!IS_ARM(board
)) {
337 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
)
340 addConversion(RawSource(SOURCE_TYPE_TELEMETRY
, i
), val
++);
341 if (version
>= 216 && IS_ARM(board
)) {
342 if (i
==TELEMETRY_SOURCE_RSSI_RX
)
344 if (i
==TELEMETRY_SOURCE_TX_TIME
)
346 if (i
==TELEMETRY_SOURCE_DTE
)
348 if (i
==TELEMETRY_SOURCE_POWER_MAX
)
358 void addConversion(const RawSource
& source
, const int b
)
360 ConversionTable::addConversion(source
.toValue(), b
);
365 Cache(BoardEnum board
, unsigned int version
, unsigned int variant
, unsigned long flags
, SourcesConversionTable
* table
):
374 unsigned int version
;
375 unsigned int variant
;
377 SourcesConversionTable
* table
;
379 static std::list
<Cache
> internalCache
;
383 static SourcesConversionTable
* getInstance(BoardEnum board
, unsigned int version
, unsigned int variant
, unsigned long flags
=0)
385 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
387 if (element
.board
== board
&& element
.version
== version
&& element
.variant
== variant
&& element
.flags
== flags
)
388 return element
.table
;
391 Cache
element(board
, version
, variant
, flags
, new SourcesConversionTable(board
, version
, variant
, flags
));
392 internalCache
.push_back(element
);
393 return element
.table
;
395 static void Cleanup()
397 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
399 delete element
.table
;
401 internalCache
.clear();
405 std::list
<SourcesConversionTable::Cache
> SourcesConversionTable::internalCache
;
407 void OpenTxEepromCleanup(void)
409 SourcesConversionTable::Cleanup();
410 SwitchesConversionTable::Cleanup();
414 class SwitchField
: public ConversionField
< SignedField
<N
> > {
416 SwitchField(RawSwitch
& sw
, BoardEnum board
, unsigned int version
, unsigned long flags
=0):
417 ConversionField
< SignedField
<N
> >(_switch
, SwitchesConversionTable::getInstance(board
, version
, flags
), QObject::tr("Switch").toLatin1(),
418 QObject::tr("Switch ").toLatin1()+ sw
.toString()+ QObject::tr(" cannot be exported on this board!").toLatin1()),
424 virtual ~SwitchField()
428 virtual void beforeExport()
430 _switch
= sw
.toValue();
431 ConversionField
< SignedField
<N
> >::beforeExport();
434 virtual void afterImport()
436 ConversionField
< SignedField
<N
> >::afterImport();
437 sw
= RawSwitch(_switch
);
438 eepromImportDebug() << QString("imported %1: %2").arg(ConversionField
< SignedField
<N
> >::internalField
.getName()).arg(sw
.toString());
446 class TelemetrySourcesConversionTable
: public ConversionTable
{
449 TelemetrySourcesConversionTable(BoardEnum board
, unsigned int version
)
453 if (IS_AFTER_RELEASE_21_MARCH_2013(board
, version
)) {
454 addConversion(0, val
++);
457 addConversion(1+TELEMETRY_SOURCE_TX_BATT
, val
++);
458 if (IS_ARM(board
) && version
>= 216) {
459 addConversion(1+TELEMETRY_SOURCE_TX_TIME
, val
++);
460 for (int i
=0; i
<5; i
++)
461 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
463 addConversion(1+TELEMETRY_SOURCE_TIMER1
, val
++);
464 addConversion(1+TELEMETRY_SOURCE_TIMER2
, val
++);
465 if (IS_ARM(board
) && version
>= 217)
466 addConversion(1+TELEMETRY_SOURCE_TIMER3
, val
++);
467 if (IS_ARM(board
) && version
>= 216)
468 addConversion(1+TELEMETRY_SOURCE_SWR
, val
++);
469 addConversion(1+TELEMETRY_SOURCE_RSSI_TX
, val
++);
470 addConversion(1+TELEMETRY_SOURCE_RSSI_RX
, val
++);
471 if (IS_ARM(board
) && version
>= 216)
472 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
473 addConversion(1+TELEMETRY_SOURCE_A1
, val
++);
474 addConversion(1+TELEMETRY_SOURCE_A2
, val
++);
475 if (IS_ARM(board
) && version
>= 216) {
476 addConversion(1+TELEMETRY_SOURCE_A3
, val
++);
477 addConversion(1+TELEMETRY_SOURCE_A4
, val
++);
479 addConversion(1+TELEMETRY_SOURCE_ALT
, val
++);
480 addConversion(1+TELEMETRY_SOURCE_RPM
, val
++);
481 addConversion(1+TELEMETRY_SOURCE_FUEL
, val
++);
482 addConversion(1+TELEMETRY_SOURCE_T1
, val
++);
483 addConversion(1+TELEMETRY_SOURCE_T2
, val
++);
484 addConversion(1+TELEMETRY_SOURCE_SPEED
, val
++);
485 addConversion(1+TELEMETRY_SOURCE_DIST
, val
++);
486 addConversion(1+TELEMETRY_SOURCE_GPS_ALT
, val
++);
487 addConversion(1+TELEMETRY_SOURCE_CELL
, val
++);
488 addConversion(1+TELEMETRY_SOURCE_CELLS_SUM
, val
++);
489 addConversion(1+TELEMETRY_SOURCE_VFAS
, val
++);
490 addConversion(1+TELEMETRY_SOURCE_CURRENT
, val
++);
491 addConversion(1+TELEMETRY_SOURCE_CONSUMPTION
, val
++);
492 addConversion(1+TELEMETRY_SOURCE_POWER
, val
++);
493 addConversion(1+TELEMETRY_SOURCE_ACCX
, val
++);
494 addConversion(1+TELEMETRY_SOURCE_ACCY
, val
++);
495 addConversion(1+TELEMETRY_SOURCE_ACCZ
, val
++);
496 addConversion(1+TELEMETRY_SOURCE_HDG
, val
++);
497 addConversion(1+TELEMETRY_SOURCE_VERTICAL_SPEED
, val
++);
498 if (version
>= 216) {
499 addConversion(1+TELEMETRY_SOURCE_ASPEED
, val
++);
500 addConversion(1+TELEMETRY_SOURCE_DTE
, val
++);
502 if (IS_ARM(board
) && version
>= 216) {
503 for (int i
=0; i
<5; i
++)
504 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
506 addConversion(1+TELEMETRY_SOURCE_A1_MIN
, val
++);
507 addConversion(1+TELEMETRY_SOURCE_A2_MIN
, val
++);
508 if (IS_ARM(board
) && version
>= 216) {
509 addConversion(1+TELEMETRY_SOURCE_A3_MIN
, val
++);
510 addConversion(1+TELEMETRY_SOURCE_A4_MIN
, val
++);
512 addConversion(1+TELEMETRY_SOURCE_ALT_MIN
, val
++);
513 addConversion(1+TELEMETRY_SOURCE_ALT_MAX
, val
++);
514 addConversion(1+TELEMETRY_SOURCE_RPM_MAX
, val
++);
515 addConversion(1+TELEMETRY_SOURCE_T1_MAX
, val
++);
516 addConversion(1+TELEMETRY_SOURCE_T2_MAX
, val
++);
517 addConversion(1+TELEMETRY_SOURCE_SPEED_MAX
, val
++);
518 addConversion(1+TELEMETRY_SOURCE_DIST_MAX
, val
++);
519 if (version
>= 216) {
520 addConversion(1+TELEMETRY_SOURCE_ASPEED_MAX
, val
++);
521 addConversion(1+TELEMETRY_SOURCE_CELL_MIN
, val
++);
522 addConversion(1+TELEMETRY_SOURCE_CELLS_MIN
, val
++);
523 addConversion(1+TELEMETRY_SOURCE_VFAS_MIN
, val
++);
525 addConversion(1+TELEMETRY_SOURCE_CURRENT_MAX
, val
++);
526 addConversion(1+TELEMETRY_SOURCE_POWER_MAX
, val
++);
527 if (IS_ARM(board
) && version
>= 216) {
528 for (int i
=0; i
<5; i
++)
529 addConversion(1+TELEMETRY_SOURCE_RESERVE
, val
++);
531 addConversion(1+TELEMETRY_SOURCE_ACC
, val
++);
532 addConversion(1+TELEMETRY_SOURCE_GPS_TIME
, val
++);
537 class TelemetrySourceField
: public ConversionField
< UnsignedField
<N
> > {
539 TelemetrySourceField(RawSource
& source
, BoardEnum board
, unsigned int version
):
540 ConversionField
< UnsignedField
<N
> >(_source
, &conversionTable
, "Telemetry source"),
541 conversionTable(board
, version
),
549 virtual ~TelemetrySourceField()
553 virtual void beforeExport()
555 _source
= (source
.type
== SOURCE_TYPE_TELEMETRY
? source
.index
+1 : 0);
556 ConversionField
< UnsignedField
<N
> >::beforeExport();
559 virtual void afterImport()
561 ConversionField
< UnsignedField
<N
> >::afterImport();
562 source
= (_source
== 0 ? RawSource(0) : RawSource(SOURCE_TYPE_TELEMETRY
, _source
-1));
563 eepromImportDebug() << QString("imported %1: %2").arg(ConversionField
< UnsignedField
<N
> >::internalField
.getName()).arg(source
.toString());
567 TelemetrySourcesConversionTable conversionTable
;
570 unsigned int version
;
571 unsigned int _source
;
575 class SourceField
: public ConversionField
< UnsignedField
<N
> > {
577 SourceField(RawSource
& source
, BoardEnum board
, unsigned int version
, unsigned int variant
, unsigned long flags
=0):
578 ConversionField
< UnsignedField
<N
> >(_source
, SourcesConversionTable::getInstance(board
, version
, variant
, flags
),
579 "Source", QObject::tr("Source %1 cannot be exported on this board!").arg(source
.toString())),
585 virtual ~SourceField()
589 virtual void beforeExport()
591 _source
= source
.toValue();
592 ConversionField
< UnsignedField
<N
> >::beforeExport();
595 virtual void afterImport()
597 ConversionField
< UnsignedField
<N
> >::afterImport();
598 source
= RawSource(_source
);
599 eepromImportDebug() << QString("imported %1: %2").arg(ConversionField
< UnsignedField
<N
> >::internalField
.getName()).arg(source
.toString());
604 unsigned int _source
;
608 int smallGvarToEEPROM(int gvar
)
611 gvar
= 128 + gvar
+ 10000;
613 else if (gvar
> 10000) {
614 gvar
= -128 +gvar
- 10001;
619 int smallGvarToC9x(int gvar
)
622 gvar
= gvar
- 128 - 10000;
624 else if (gvar
< -110) {
625 gvar
= gvar
+ 128 + 10001;
630 void splitGvarParam(const int gvar
, int & _gvar
, unsigned int & _gvarParam
, const BoardEnum board
, const int version
)
632 if (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) {
635 _gvar
= 256 + gvar
+ 10000;
637 else if (gvar
> 10000) {
639 _gvar
= gvar
- 10001;
642 if (gvar
< 0) _gvarParam
= 1;
644 _gvar
= gvar
; // save routine throws away all unused bits; therefore no 2er complement compensation needed here
650 _gvar
= gvar
+ 10000;
652 else if (gvar
> 10000) {
654 _gvar
= gvar
- 10001;
663 void concatGvarParam(int & gvar
, const int _gvar
, const unsigned int _gvarParam
, const BoardEnum board
, const int version
)
665 if (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) {
667 if (gvar
<0) gvar
+=256; // remove 2er complement, because 8bit part is in this case unsigned
668 if (_gvarParam
) { // here is the real sign bit
669 gvar
|=-256; // set all higher bits to simulate negative value
673 gvar
= gvar
-256 - 10000;
674 } else if (gvar
<-245) {
675 gvar
= gvar
+256 + 10001;
679 if (_gvarParam
== 0) {
682 else if (_gvar
>= 0) {
683 gvar
= 10001 + _gvar
;
686 gvar
= -10000 + _gvar
;
691 void exportGvarParam(const int gvar
, int & _gvar
, int version
)
693 int GV1
= (version
>= 217 ? 1024 : (version
>= 216 ? 4096 : 512));
696 _gvar
= GV1
+ gvar
+ 10000;
698 else if (gvar
> 10000) {
699 _gvar
= GV1
+ gvar
- 10001;
706 void importGvarParam(int & gvar
, const int _gvar
, int version
)
708 int GV1
= (version
>= 217 ? 1024 : (version
>= 216 ? 4096 : 512));
711 gvar
= 10001 + _gvar
- GV1
;
713 else if (_gvar
>= GV1
-9) {
714 gvar
= -10000 + _gvar
- GV1
;
716 else if (_gvar
< -GV1
) {
717 gvar
= -10000 + _gvar
+ GV1
+ 1;
719 else if (_gvar
< -GV1
+9) {
720 gvar
= 10000 + _gvar
+ GV1
+ 1;
726 // qDebug() << QString("import") << _gvar << gvar;
729 class CurveReferenceField
: public TransformedField
{
731 CurveReferenceField(CurveReference
& curve
, BoardEnum board
, unsigned int version
):
732 TransformedField(internalField
),
737 internalField
.Append(new UnsignedField
<8>(_curve_type
));
738 internalField
.Append(new SignedField
<8>(_curve_value
));
741 virtual void beforeExport()
743 if (curve
.value
!= 0) {
744 _curve_type
= (unsigned int)curve
.type
;
745 _curve_value
= smallGvarToEEPROM(curve
.value
);
753 virtual void afterImport()
755 curve
.type
= (CurveReference::CurveRefType
)_curve_type
;
756 curve
.value
= smallGvarToC9x(_curve_value
);
757 eepromImportDebug() << QString("imported CurveReference(%1)").arg(curve
.toString());
761 StructField internalField
;
762 CurveReference
& curve
;
763 unsigned int _curve_type
;
767 static int exportHeliInversionWeight(int source
) {
768 return (source
< 0) ? 1 : 0;
771 static int importHeliInversionWeight(int source
) {
772 return source
? -100: 100;
775 class HeliField
: public StructField
{
777 HeliField(SwashRingData
& heli
, BoardEnum board
, unsigned int version
, unsigned int variant
)
779 if (IS_STM32(board
) && version
>= 217) {
780 Append(new UnsignedField
<8>(heli
.type
));
781 Append(new UnsignedField
<8>(heli
.value
));
782 Append(new SourceField
<8>(heli
.collectiveSource
, board
, version
, variant
));
783 Append(new SourceField
<8>(heli
.aileronSource
, board
, version
, variant
));
784 Append(new SourceField
<8>(heli
.elevatorSource
, board
, version
, variant
));
785 Append(new SignedField
<8>(heli
.collectiveWeight
));
786 Append(new SignedField
<8>(heli
.aileronWeight
));
787 Append(new SignedField
<8>(heli
.elevatorWeight
));
790 Append(new ConversionField
< SignedField
<1> >(heli
.elevatorWeight
, exportHeliInversionWeight
, importHeliInversionWeight
));
791 Append(new ConversionField
< SignedField
<1> >(heli
.aileronWeight
, exportHeliInversionWeight
, importHeliInversionWeight
));
792 Append(new ConversionField
< SignedField
<1> >(heli
.collectiveWeight
, exportHeliInversionWeight
, importHeliInversionWeight
));
793 Append(new UnsignedField
<5>(heli
.type
));
794 Append(new SourceField
<8>(heli
.collectiveSource
, board
, version
, variant
));
795 //, FLAG_NOSWITCHES)); Fix shift in collective
796 Append(new UnsignedField
<8>(heli
.value
));
801 class FlightModeField
: public TransformedField
{
803 FlightModeField(FlightModeData
& phase
, int index
, BoardEnum board
, unsigned int version
):
804 TransformedField(internalField
),
805 internalField("FlightMode"),
810 rotencCount(ROTENC_COUNT(board
, version
))
812 if (board
== BOARD_STOCK
|| (board
==BOARD_M128
&& version
>=215)) {
813 // On stock we use 10bits per trim
814 for (int i
=0; i
<CPN_MAX_STICKS
; i
++)
815 internalField
.Append(new SignedField
<8>(trimBase
[i
]));
816 for (int i
=0; i
<CPN_MAX_STICKS
; i
++)
817 internalField
.Append(new SignedField
<2>(trimExt
[i
]));
819 else if (IS_ARM(board
) && version
>= 218) {
820 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_AUX_TRIMS(board
); i
++) {
821 internalField
.Append(new SignedField
<11>(phase
.trim
[i
]));
822 internalField
.Append(new UnsignedField
<5>(trimMode
[i
]));
825 else if (IS_TARANIS(board
) && version
>= 216) {
826 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
827 internalField
.Append(new SignedField
<11>(phase
.trim
[i
]));
828 internalField
.Append(new UnsignedField
<5>(trimMode
[i
]));
832 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
833 internalField
.Append(new SignedField
<16>(trimBase
[i
]));
836 if (IS_ARM(board
) && version
>= 218) {
837 if (HAS_LARGE_LCD(board
))
838 internalField
.Append(new ZCharField
<10>(phase
.name
, "Flight mode name"));
840 internalField
.Append(new ZCharField
<6>(phase
.name
, "Flight mode name"));
841 internalField
.Append(new SwitchField
<9>(phase
.swtch
, board
, version
));
842 internalField
.Append(new SpareBitsField
<7>());
845 internalField
.Append(new SwitchField
<8>(phase
.swtch
, board
, version
));
846 if (HAS_LARGE_LCD(board
))
847 internalField
.Append(new ZCharField
<10>(phase
.name
));
849 internalField
.Append(new ZCharField
<6>(phase
.name
));
851 if (IS_ARM(board
) && version
>= 214) {
852 internalField
.Append(new UnsignedField
<8>(phase
.fadeIn
));
853 internalField
.Append(new UnsignedField
<8>(phase
.fadeOut
));
856 internalField
.Append(new UnsignedField
<4>(phase
.fadeIn
));
857 internalField
.Append(new UnsignedField
<4>(phase
.fadeOut
));
860 for (int i
=0; i
<rotencCount
; i
++) {
861 internalField
.Append(new SignedField
<16>(phase
.rotaryEncoders
[i
]));
864 if (board
!= BOARD_STOCK
&& (board
!= BOARD_M128
|| version
< 215)) {
865 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
866 internalField
.Append(new SignedField
<16>(phase
.gvars
[i
]));
871 virtual void beforeExport()
873 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_AUX_TRIMS(board
); i
++) {
874 if (IS_HORUS_OR_TARANIS(board
) && version
>= 216) {
875 if (phase
.trimMode
[i
] < 0)
876 trimMode
[i
] = TRIM_MODE_NONE
;
878 trimMode
[i
] = 2*phase
.trimRef
[i
] + phase
.trimMode
[i
];
882 if (phase
.trimMode
[i
] < 0)
884 else if (phase
.trimRef
[i
] != index
)
885 trim
= 501 + phase
.trimRef
[i
] - (phase
.trimRef
[i
] > index
? 1 : 0);
887 trim
= std::max(-500, std::min(500, phase
.trim
[i
]));
888 if (board
== BOARD_STOCK
|| (board
== BOARD_M128
&& version
>= 215)) {
889 trimBase
[i
] = trim
>> 2;
890 trimExt
[i
] = (trim
& 0x03);
899 virtual void afterImport()
901 for (int i
=0; i
<CPN_MAX_STICKS
+MAX_AUX_TRIMS(board
); i
++) {
902 if (IS_HORUS_OR_TARANIS(board
) && version
>= 216) {
903 if (trimMode
[i
] == TRIM_MODE_NONE
) {
904 phase
.trimMode
[i
] = -1;
907 phase
.trimMode
[i
] = trimMode
[i
] % 2;
908 phase
.trimRef
[i
] = trimMode
[i
] / 2;
912 if (phase
.swtch
== RawSwitch(SWITCH_TYPE_NONE
) && index
> 0) {
913 phase
.trimRef
[i
] = 0;
914 phase
.trimMode
[i
] = 0;
919 if (board
== BOARD_STOCK
|| (board
== BOARD_M128
&& version
>= 215))
920 trim
= ((trimBase
[i
]) << 2) + (trimExt
[i
] & 0x03);
924 phase
.trimRef
[i
] = trim
- 501;
925 if (phase
.trimRef
[i
] >= index
)
926 phase
.trimRef
[i
] += 1;
927 phase
.trimMode
[i
] = 0;
931 phase
.trimRef
[i
] = index
/*own trim*/;
932 phase
.trimMode
[i
] = 0;
933 phase
.trim
[i
] = trim
;
938 eepromImportDebug() << QString("imported %1: '%2'").arg(internalField
.getName()).arg(phase
.name
);
942 StructField internalField
;
943 FlightModeData
& phase
;
946 unsigned int version
;
948 int trimBase
[CPN_MAX_STICKS
+CPN_MAX_AUX_TRIMS
];
949 int trimExt
[CPN_MAX_STICKS
+CPN_MAX_AUX_TRIMS
];
950 unsigned int trimMode
[CPN_MAX_STICKS
+CPN_MAX_AUX_TRIMS
];
953 class MixField
: public TransformedField
{
955 MixField(MixData
& mix
, BoardEnum board
, unsigned int version
, ModelData
* model
):
956 TransformedField(internalField
),
957 internalField("Mix"),
963 if (IS_ARM(board
) && version
>= 218) {
964 internalField
.Append(new SignedField
<11>(_weight
));
965 internalField
.Append(new UnsignedField
<5>(_destCh
));
966 internalField
.Append(new SourceField
<10>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
967 internalField
.Append(new UnsignedField
<1>((unsigned int &)mix
.carryTrim
));
968 internalField
.Append(new UnsignedField
<2>(mix
.mixWarn
));
969 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
970 internalField
.Append(new SpareBitsField
<1>());
971 internalField
.Append(new SignedField
<14>(_offset
));
972 internalField
.Append(new SwitchField
<9>(mix
.swtch
, board
, version
));
973 internalField
.Append(new UnsignedField
<9>(mix
.flightModes
));
974 internalField
.Append(new CurveReferenceField(mix
.curve
, board
, version
));
975 internalField
.Append(new UnsignedField
<8>(mix
.delayUp
));
976 internalField
.Append(new UnsignedField
<8>(mix
.delayDown
));
977 internalField
.Append(new UnsignedField
<8>(mix
.speedUp
));
978 internalField
.Append(new UnsignedField
<8>(mix
.speedDown
));
980 internalField
.Append(new ZCharField
<6>(mix
.name
));
981 else if (HAS_LARGE_LCD(board
))
982 internalField
.Append(new ZCharField
<8>(mix
.name
));
984 internalField
.Append(new ZCharField
<6>(mix
.name
));
986 else if (IS_TARANIS(board
) && version
>= 217) {
987 internalField
.Append(new UnsignedField
<8>(_destCh
));
988 internalField
.Append(new UnsignedField
<9>(mix
.flightModes
));
989 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
990 internalField
.Append(new UnsignedField
<1>((unsigned int &)mix
.carryTrim
));
991 internalField
.Append(new UnsignedField
<4>(mix
.mixWarn
));
992 internalField
.Append(new SignedField
<16>(_weight
));
993 internalField
.Append(new SourceField
<10>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
994 internalField
.Append(new SignedField
<14>(_offset
));
995 internalField
.Append(new SwitchField
<8>(mix
.swtch
, board
, version
));
996 internalField
.Append(new CurveReferenceField(mix
.curve
, board
, version
));
997 internalField
.Append(new UnsignedField
<8>(mix
.delayUp
));
998 internalField
.Append(new UnsignedField
<8>(mix
.delayDown
));
999 internalField
.Append(new UnsignedField
<8>(mix
.speedUp
));
1000 internalField
.Append(new UnsignedField
<8>(mix
.speedDown
));
1001 internalField
.Append(new ZCharField
<8>(mix
.name
));
1003 else if (IS_ARM(board
) && version
>= 217) {
1004 internalField
.Append(new UnsignedField
<5>(_destCh
));
1005 internalField
.Append(new UnsignedField
<3>(mix
.mixWarn
));
1006 internalField
.Append(new UnsignedField
<9>(mix
.flightModes
));
1007 internalField
.Append(new BoolField
<1>(_curveMode
));
1008 internalField
.Append(new BoolField
<1>(mix
.noExpo
));
1009 internalField
.Append(new SignedField
<3>(mix
.carryTrim
));
1010 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
1011 internalField
.Append(new SignedField
<16>(_weight
));
1012 internalField
.Append(new SwitchField
<8>(mix
.swtch
, board
, version
));
1013 internalField
.Append(new SignedField
<8>(_curveParam
));
1014 internalField
.Append(new UnsignedField
<8>(mix
.delayUp
));
1015 internalField
.Append(new UnsignedField
<8>(mix
.delayDown
));
1016 internalField
.Append(new UnsignedField
<8>(mix
.speedUp
));
1017 internalField
.Append(new UnsignedField
<8>(mix
.speedDown
));
1018 internalField
.Append(new SourceField
<8>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1019 internalField
.Append(new SignedField
<16>(_offset
));
1020 internalField
.Append(new ZCharField
<6>(mix
.name
));
1022 else if (IS_TARANIS(board
) && version
== 216) {
1023 internalField
.Append(new UnsignedField
<8>(_destCh
));
1024 internalField
.Append(new UnsignedField
<16>(mix
.flightModes
));
1025 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
1026 internalField
.Append(new UnsignedField
<1>((unsigned int &)mix
.carryTrim
));
1027 internalField
.Append(new SpareBitsField
<5>());
1028 internalField
.Append(new SignedField
<16>(_weight
));
1029 internalField
.Append(new SwitchField
<8>(mix
.swtch
, board
, version
));
1030 internalField
.Append(new CurveReferenceField(mix
.curve
, board
, version
));
1031 internalField
.Append(new UnsignedField
<4>(mix
.mixWarn
));
1032 internalField
.Append(new SpareBitsField
<4>());
1033 internalField
.Append(new UnsignedField
<8>(mix
.delayUp
));
1034 internalField
.Append(new UnsignedField
<8>(mix
.delayDown
));
1035 internalField
.Append(new UnsignedField
<8>(mix
.speedUp
));
1036 internalField
.Append(new UnsignedField
<8>(mix
.speedDown
));
1037 internalField
.Append(new SourceField
<8>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1038 internalField
.Append(new SignedField
<16>(_offset
));
1039 internalField
.Append(new ZCharField
<8>(mix
.name
));
1040 internalField
.Append(new SpareBitsField
<8>());
1042 else if (IS_ARM(board
) && version
== 216) {
1043 internalField
.Append(new UnsignedField
<5>(_destCh
));
1044 internalField
.Append(new UnsignedField
<3>(mix
.mixWarn
));
1045 internalField
.Append(new UnsignedField
<16>(mix
.flightModes
));
1046 internalField
.Append(new BoolField
<1>(_curveMode
));
1047 internalField
.Append(new BoolField
<1>(mix
.noExpo
));
1048 internalField
.Append(new SignedField
<3>(mix
.carryTrim
));
1049 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
1050 internalField
.Append(new SpareBitsField
<1>());
1051 internalField
.Append(new SignedField
<16>(_weight
));
1052 internalField
.Append(new SwitchField
<8>(mix
.swtch
, board
, version
));
1053 internalField
.Append(new SignedField
<8>(_curveParam
));
1054 internalField
.Append(new UnsignedField
<8>(mix
.delayUp
));
1055 internalField
.Append(new UnsignedField
<8>(mix
.delayDown
));
1056 internalField
.Append(new UnsignedField
<8>(mix
.speedUp
));
1057 internalField
.Append(new UnsignedField
<8>(mix
.speedDown
));
1058 internalField
.Append(new SourceField
<8>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1059 internalField
.Append(new SignedField
<16>(_offset
));
1060 internalField
.Append(new ZCharField
<6>(mix
.name
));
1062 else if (IS_ARM(board
)) {
1063 internalField
.Append(new UnsignedField
<8>(_destCh
));
1064 internalField
.Append(new UnsignedField
<16>(mix
.flightModes
));
1065 internalField
.Append(new BoolField
<1>(_curveMode
));
1066 internalField
.Append(new BoolField
<1>(mix
.noExpo
));
1067 internalField
.Append(new SignedField
<3>(mix
.carryTrim
));
1068 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
1070 internalField
.Append(new SpareBitsField
<1>());
1072 internalField
.Append(new UnsignedField
<1>(_offsetMode
));
1073 internalField
.Append(new SignedField
<16>(_weight
));
1074 internalField
.Append(new SwitchField
<8>(mix
.swtch
, board
, version
));
1075 internalField
.Append(new SignedField
<8>(_curveParam
));
1076 if (version
>= 214) {
1077 internalField
.Append(new UnsignedField
<4>(mix
.mixWarn
));
1078 internalField
.Append(new SpareBitsField
<4>());
1081 internalField
.Append(new UnsignedField
<8>(mix
.mixWarn
));
1083 internalField
.Append(new UnsignedField
<8>(mix
.delayUp
));
1084 internalField
.Append(new UnsignedField
<8>(mix
.delayDown
));
1085 internalField
.Append(new UnsignedField
<8>(mix
.speedUp
));
1086 internalField
.Append(new UnsignedField
<8>(mix
.speedDown
));
1087 internalField
.Append(new SourceField
<8>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1089 internalField
.Append(new SignedField
<16>(_offset
));
1091 internalField
.Append(new SignedField
<8>(_offset
));
1092 if (HAS_LARGE_LCD(board
)) {
1093 internalField
.Append(new ZCharField
<8>(mix
.name
));
1094 internalField
.Append(new SpareBitsField
<16>());
1097 internalField
.Append(new ZCharField
<6>(mix
.name
));
1100 else if (IS_DBLRAM(board
, version
) && IS_AFTER_RELEASE_23_MARCH_2013(board
, version
)) {
1101 internalField
.Append(new UnsignedField
<4>(_destCh
));
1102 internalField
.Append(new BoolField
<1>(_curveMode
));
1103 internalField
.Append(new BoolField
<1>(mix
.noExpo
));
1104 internalField
.Append(new UnsignedField
<1>(_weightMode
));
1105 internalField
.Append(new UnsignedField
<1>(_offsetMode
));
1106 internalField
.Append(new SourceField
<8>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1107 internalField
.Append(new SignedField
<8>(_weight
));
1108 internalField
.Append(new SwitchField
<8>(mix
.swtch
, board
, version
));
1109 internalField
.Append(new UnsignedField
<8>(mix
.flightModes
));
1110 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
1111 internalField
.Append(new SignedField
<3>(mix
.carryTrim
));
1112 internalField
.Append(new UnsignedField
<2>(mix
.mixWarn
));
1113 internalField
.Append(new SpareBitsField
<1>());
1114 internalField
.Append(new UnsignedField
<4>(mix
.delayUp
));
1115 internalField
.Append(new UnsignedField
<4>(mix
.delayDown
));
1116 internalField
.Append(new UnsignedField
<4>(mix
.speedUp
));
1117 internalField
.Append(new UnsignedField
<4>(mix
.speedDown
));
1118 internalField
.Append(new SignedField
<8>(_curveParam
));
1119 internalField
.Append(new SignedField
<8>(_offset
));
1122 internalField
.Append(new UnsignedField
<4>(_destCh
));
1123 internalField
.Append(new BoolField
<1>(_curveMode
));
1124 internalField
.Append(new BoolField
<1>(mix
.noExpo
));
1125 internalField
.Append(new UnsignedField
<1>(_weightMode
));
1126 internalField
.Append(new UnsignedField
<1>(_offsetMode
));
1127 internalField
.Append(new SignedField
<8>(_weight
));
1128 internalField
.Append(new SwitchField
<6>(mix
.swtch
, board
, version
));
1129 internalField
.Append(new UnsignedField
<2>((unsigned int &)mix
.mltpx
));
1130 internalField
.Append(new UnsignedField
<5>(mix
.flightModes
));
1131 internalField
.Append(new SignedField
<3>(mix
.carryTrim
));
1132 internalField
.Append(new SourceField
<6>(mix
.srcRaw
, board
, version
, FLAG_NOTELEMETRY
));
1133 internalField
.Append(new UnsignedField
<2>(mix
.mixWarn
));
1134 internalField
.Append(new UnsignedField
<4>(mix
.delayUp
));
1135 internalField
.Append(new UnsignedField
<4>(mix
.delayDown
));
1136 internalField
.Append(new UnsignedField
<4>(mix
.speedUp
));
1137 internalField
.Append(new UnsignedField
<4>(mix
.speedDown
));
1138 internalField
.Append(new SignedField
<8>(_curveParam
));
1139 internalField
.Append(new SignedField
<8>(_offset
));
1143 virtual void beforeExport()
1145 if (mix
.destCh
&& mix
.srcRaw
.type
!= SOURCE_TYPE_NONE
) {
1146 _destCh
= mix
.destCh
- 1;
1147 if (mix
.curve
.type
== CurveReference::CURVE_REF_CUSTOM
) {
1149 if (mix
.curve
.value
> 0) {
1150 _curveParam
= 6 + mix
.curve
.value
;
1153 _curveParam
= mix
.curve
.value
;
1156 else if (mix
.curve
.type
== CurveReference::CURVE_REF_FUNC
) {
1158 _curveParam
= mix
.curve
.value
;
1160 else if (mix
.curve
.type
== CurveReference::CURVE_REF_DIFF
) {
1162 _curveParam
= smallGvarToEEPROM(mix
.curve
.value
);
1172 if (IS_ARM(board
)) {
1173 exportGvarParam(mix
.weight
, _weight
, version
);
1175 exportGvarParam(mix
.sOffset
, _offset
, version
);
1177 splitGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1180 splitGvarParam(mix
.weight
, _weight
, _weightMode
, board
, version
);
1181 splitGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1185 virtual void afterImport()
1187 if (IS_TARANIS(board
) && version
< 216) {
1188 if (mix
.srcRaw
.type
== SOURCE_TYPE_STICK
&& mix
.srcRaw
.index
< CPN_MAX_STICKS
) {
1190 mix
.srcRaw
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, mix
.srcRaw
.index
);
1195 if (mix
.srcRaw
.type
!= SOURCE_TYPE_NONE
) {
1196 mix
.destCh
= _destCh
+ 1;
1197 if (!IS_STM32(board
) || version
< 216) {
1199 mix
.curve
= CurveReference(CurveReference::CURVE_REF_DIFF
, smallGvarToC9x(_curveParam
));
1200 else if (_curveParam
> 6)
1201 mix
.curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, _curveParam
-6);
1202 else if (_curveParam
< 0)
1203 mix
.curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, _curveParam
);
1205 mix
.curve
= CurveReference(CurveReference::CURVE_REF_FUNC
, _curveParam
);
1209 if (IS_ARM(board
)) {
1210 importGvarParam(mix
.weight
, _weight
, version
);
1212 importGvarParam(mix
.sOffset
, _offset
, version
);
1214 concatGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1217 concatGvarParam(mix
.weight
, _weight
, _weightMode
, board
, version
);
1218 concatGvarParam(mix
.sOffset
, _offset
, _offsetMode
, board
, version
);
1221 if (IS_TARANIS(board
) && version
< 216) {
1222 if (mix
.sOffset
>= -500 && mix
.sOffset
<= 500 && mix
.weight
>= -500 && mix
.weight
<= 500) {
1223 mix
.sOffset
= divRoundClosest(mix
.sOffset
* mix
.weight
, 100);
1225 if (mix
.carryTrim
< 0) mix
.carryTrim
= 0;
1227 eepromImportDebug() << QString("imported %1: ch %2, name '%3'").arg(internalField
.getName()).arg(mix
.destCh
).arg(mix
.name
);
1231 StructField internalField
;
1234 unsigned int version
;
1236 unsigned int _destCh
;
1241 unsigned int _weightMode
;
1242 unsigned int _offsetMode
;
1245 class InputField
: public TransformedField
{
1247 InputField(ExpoData
& expo
, BoardEnum board
, unsigned int version
):
1248 TransformedField(internalField
),
1249 internalField("Input"),
1254 if (IS_ARM(board
) && version
>= 218) {
1255 internalField
.Append(new UnsignedField
<2>(expo
.mode
, "Mode"));
1256 internalField
.Append(new UnsignedField
<14>(expo
.scale
, "Scale"));
1257 internalField
.Append(new SourceField
<10>(expo
.srcRaw
, board
, version
, 0));
1258 internalField
.Append(new SignedField
<6>(expo
.carryTrim
, "CarryTrim"));
1259 internalField
.Append(new UnsignedField
<5>(expo
.chn
, "Channel"));
1260 internalField
.Append(new SwitchField
<9>(expo
.swtch
, board
, version
));
1261 internalField
.Append(new UnsignedField
<9>(expo
.flightModes
));
1262 internalField
.Append(new SignedField
<8>(_weight
, "Weight"));
1263 internalField
.Append(new SpareBitsField
<1>());
1264 if (IS_HORUS(board
))
1265 internalField
.Append(new ZCharField
<6>(expo
.name
));
1266 else if (HAS_LARGE_LCD(board
))
1267 internalField
.Append(new ZCharField
<8>(expo
.name
));
1269 internalField
.Append(new ZCharField
<6>(expo
.name
));
1270 internalField
.Append(new SignedField
<8>(_offset
, "Offset"));
1271 internalField
.Append(new CurveReferenceField(expo
.curve
, board
, version
));
1273 else if (IS_TARANIS(board
) && version
>= 217) {
1274 internalField
.Append(new SourceField
<10>(expo
.srcRaw
, board
, version
, 0));
1275 internalField
.Append(new UnsignedField
<14>(expo
.scale
, "Scale"));
1276 internalField
.Append(new UnsignedField
<8>(expo
.chn
, "Channel"));
1277 internalField
.Append(new SwitchField
<8>(expo
.swtch
, board
, version
));
1278 internalField
.Append(new UnsignedField
<16>(expo
.flightModes
));
1279 internalField
.Append(new SignedField
<8>(_weight
, "Weight"));
1280 internalField
.Append(new SignedField
<6>(expo
.carryTrim
, "CarryTrim"));
1281 internalField
.Append(new UnsignedField
<2>(expo
.mode
, "Mode"));
1282 internalField
.Append(new ZCharField
<8>(expo
.name
));
1283 internalField
.Append(new SignedField
<8>(_offset
, "Offset"));
1284 internalField
.Append(new CurveReferenceField(expo
.curve
, board
, version
));
1286 else if (IS_ARM(board
) && version
>= 217) {
1287 internalField
.Append(new UnsignedField
<2>(expo
.mode
, "Mode"));
1288 internalField
.Append(new UnsignedField
<3>(expo
.chn
, "Channel"));
1289 internalField
.Append(new BoolField
<2>(_curveMode
));
1290 internalField
.Append(new UnsignedField
<9>(expo
.flightModes
, "Phases"));
1291 internalField
.Append(new SwitchField
<8>(expo
.swtch
, board
, version
));
1292 internalField
.Append(new SignedField
<8>(_weight
, "Weight"));
1293 internalField
.Append(new ZCharField
<6>(expo
.name
));
1294 internalField
.Append(new SignedField
<8>(_curveParam
));
1296 else if (IS_TARANIS(board
) && version
>= 216) {
1297 internalField
.Append(new SourceField
<8>(expo
.srcRaw
, board
, version
, 0));
1298 internalField
.Append(new UnsignedField
<16>(expo
.scale
, "Scale"));
1299 internalField
.Append(new UnsignedField
<8>(expo
.chn
, "Channel"));
1300 internalField
.Append(new SwitchField
<8>(expo
.swtch
, board
, version
));
1301 internalField
.Append(new UnsignedField
<16>(expo
.flightModes
));
1302 internalField
.Append(new SignedField
<8>(_weight
, "Weight"));
1303 internalField
.Append(new SignedField
<6>(expo
.carryTrim
, "CarryTrim"));
1304 internalField
.Append(new UnsignedField
<2>(expo
.mode
, "Mode"));
1305 internalField
.Append(new ZCharField
<8>(expo
.name
));
1306 internalField
.Append(new SignedField
<8>(_offset
, "Offset"));
1307 internalField
.Append(new CurveReferenceField(expo
.curve
, board
, version
));
1308 internalField
.Append(new SpareBitsField
<8>());
1310 else if (IS_ARM(board
) && version
>= 216) {
1311 internalField
.Append(new UnsignedField
<2>(expo
.mode
, "Mode"));
1312 internalField
.Append(new UnsignedField
<4>(expo
.chn
, "Channel"));
1313 internalField
.Append(new BoolField
<2>(_curveMode
));
1314 internalField
.Append(new SwitchField
<8>(expo
.swtch
, board
, version
));
1315 internalField
.Append(new UnsignedField
<16>(expo
.flightModes
, "Phases"));
1316 internalField
.Append(new SignedField
<8>(_weight
, "Weight"));
1317 internalField
.Append(new ZCharField
<6>(expo
.name
));
1318 internalField
.Append(new SignedField
<8>(_curveParam
));
1320 else if (IS_ARM(board
)) {
1321 internalField
.Append(new UnsignedField
<8>(expo
.mode
, "Mode"));
1322 internalField
.Append(new UnsignedField
<8>(expo
.chn
, "Channel"));
1323 internalField
.Append(new SwitchField
<8>(expo
.swtch
, board
, version
));
1324 internalField
.Append(new UnsignedField
<16>(expo
.flightModes
, "Phases"));
1325 internalField
.Append(new SignedField
<8>(_weight
, "Weight"));
1326 internalField
.Append(new BoolField
<8>(_curveMode
));
1327 if (HAS_LARGE_LCD(board
)) {
1328 internalField
.Append(new ZCharField
<8>(expo
.name
));
1329 internalField
.Append(new SpareBitsField
<16>());
1332 internalField
.Append(new ZCharField
<6>(expo
.name
));
1334 internalField
.Append(new SignedField
<8>(_curveParam
));
1336 else if (IS_DBLRAM(board
, version
) && IS_AFTER_RELEASE_23_MARCH_2013(board
, version
)) {
1337 internalField
.Append(new UnsignedField
<2>(expo
.mode
));
1338 internalField
.Append(new UnsignedField
<2>(expo
.chn
));
1339 internalField
.Append(new BoolField
<1>(_curveMode
));
1340 internalField
.Append(new SpareBitsField
<3>());
1341 internalField
.Append(new UnsignedField
<8>(expo
.flightModes
));
1342 internalField
.Append(new SwitchField
<8>(expo
.swtch
, board
, version
));
1343 internalField
.Append(new SignedField
<8>(_weight
));
1344 internalField
.Append(new SignedField
<8>(_curveParam
));
1347 internalField
.Append(new UnsignedField
<2>(expo
.mode
));
1348 internalField
.Append(new SwitchField
<6>(expo
.swtch
, board
, version
));
1349 internalField
.Append(new UnsignedField
<2>(expo
.chn
));
1350 internalField
.Append(new UnsignedField
<5>(expo
.flightModes
));
1351 internalField
.Append(new BoolField
<1>(_curveMode
));
1352 internalField
.Append(new SignedField
<8>(_weight
));
1353 internalField
.Append(new SignedField
<8>(_curveParam
));
1357 virtual void beforeExport()
1359 _weight
= smallGvarToEEPROM(expo
.weight
);
1361 if (IS_TARANIS(board
) && version
>= 216) {
1362 _offset
= smallGvarToEEPROM(expo
.offset
);
1365 if (!IS_TARANIS(board
) || version
< 216) {
1366 if (expo
.curve
.type
==CurveReference::CURVE_REF_FUNC
&& expo
.curve
.value
) {
1368 _curveParam
= expo
.curve
.value
;
1370 else if (expo
.curve
.type
==CurveReference::CURVE_REF_CUSTOM
&& expo
.curve
.value
) {
1372 _curveParam
= expo
.curve
.value
+6;
1376 _curveParam
= smallGvarToEEPROM(expo
.curve
.value
);
1381 virtual void afterImport()
1383 if (IS_STM32(board
)) {
1384 if (version
< 216) {
1386 expo
.srcRaw
= RawSource(SOURCE_TYPE_STICK
, expo
.chn
);
1390 else if (expo
.mode
) {
1391 expo
.srcRaw
= RawSource(SOURCE_TYPE_STICK
, expo
.chn
);
1394 expo
.weight
= smallGvarToC9x(_weight
);
1396 if (IS_STM32(board
) && version
>= 216) {
1397 expo
.offset
= smallGvarToC9x(_offset
);
1400 if (!IS_STM32(board
) || version
< 216) {
1402 expo
.curve
= CurveReference(CurveReference::CURVE_REF_EXPO
, smallGvarToC9x(_curveParam
));
1403 else if (_curveParam
> 6)
1404 expo
.curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, _curveParam
-6);
1406 expo
.curve
= CurveReference(CurveReference::CURVE_REF_FUNC
, _curveParam
);
1408 eepromImportDebug() << QString("imported %1: ch %2 name '%3'").arg(internalField
.getName()).arg(expo
.chn
).arg(expo
.name
);
1412 StructField internalField
;
1415 unsigned int version
;
1422 class LimitField
: public StructField
{
1424 template <int shift
, int GV1
>
1425 static int exportLimitValue(int value
)
1427 if (value
> 10000) {
1428 return -GV1
+ value
- 10001;
1430 if (value
< -10000) {
1431 return GV1
+ value
+ 10000;
1433 return value
+ shift
;
1436 template <int shift
, int GV1
>
1437 static int importLimitValue(int value
)
1440 return 10001 + value
- GV1
;
1442 if (value
>= GV1
-9) {
1443 return -10000 + value
- GV1
;
1446 return -10000 + value
+ GV1
+ 1;
1448 if (value
< -GV1
+9) {
1449 return 10000 + value
+ GV1
+ 1;
1451 return value
- shift
;
1454 LimitField(LimitData
& limit
, BoardEnum board
, unsigned int version
):
1455 StructField("Limit")
1457 if (IS_ARM(board
) && version
>= 218) {
1458 if (HAS_LARGE_LCD(board
)) {
1459 Append(new ConversionField
< SignedField
<11> >(limit
.min
, exportLimitValue
<1000, 1024>, importLimitValue
<1000, 1024>));
1460 Append(new ConversionField
< SignedField
<11> >(limit
.max
, exportLimitValue
<-1000, 1024>, importLimitValue
<-1000, 1024>));
1463 Append(new ConversionField
< SignedField
<11> >(limit
.min
, +100, 10));
1464 Append(new ConversionField
< SignedField
<11> >(limit
.max
, -100, 10));
1466 Append(new SignedField
<10>(limit
.ppmCenter
));
1467 Append(new ConversionField
< SignedField
<11> >(limit
.offset
, exportLimitValue
<0, 1024>, importLimitValue
<0, 1024>));
1468 Append(new BoolField
<1>(limit
.symetrical
));
1469 Append(new BoolField
<1>(limit
.revert
));
1470 Append(new SpareBitsField
<3>());
1471 Append(new SignedField
<8>(limit
.curve
.value
));
1472 if (HAS_LARGE_LCD(board
))
1473 Append(new ZCharField
<6>(limit
.name
));
1475 Append(new ZCharField
<4>(limit
.name
));
1477 else if (IS_TARANIS(board
) && version
>= 217) {
1478 Append(new ConversionField
< SignedField
<11> >(limit
.min
, exportLimitValue
<1000, 1024>, importLimitValue
<1000, 1024>));
1479 Append(new ConversionField
< SignedField
<11> >(limit
.max
, exportLimitValue
<-1000, 1024>, importLimitValue
<-1000, 1024>));
1480 Append(new SignedField
<10>(limit
.ppmCenter
));
1481 Append(new ConversionField
< SignedField
<11> >(limit
.offset
, exportLimitValue
<0, 1024>, importLimitValue
<0, 1024>));
1482 Append(new BoolField
<1>(limit
.symetrical
));
1483 Append(new BoolField
<1>(limit
.revert
));
1484 Append(new SpareBitsField
<3>());
1485 Append(new SignedField
<8>(limit
.curve
.value
));
1486 Append(new ZCharField
<6>(limit
.name
));
1489 if (IS_TARANIS(board
) && version
>= 216) {
1490 Append(new ConversionField
< SignedField
<16> >(limit
.min
, exportLimitValue
<1000, 4096>, importLimitValue
<1000, 4096>));
1491 Append(new ConversionField
< SignedField
<16> >(limit
.max
, exportLimitValue
<-1000, 4096>, importLimitValue
<-1000, 4096>));
1492 Append(new SignedField
<8>(limit
.ppmCenter
));
1493 Append(new ConversionField
< SignedField
<14> >(limit
.offset
, exportLimitValue
<0, 4096>, importLimitValue
<0, 4096>));
1496 Append(new ConversionField
< SignedField
<8> >(limit
.min
, +100, 10));
1497 Append(new ConversionField
< SignedField
<8> >(limit
.max
, -100, 10));
1498 Append(new SignedField
<8>(limit
.ppmCenter
));
1499 Append(new SignedField
<14>(limit
.offset
));
1501 Append(new BoolField
<1>(limit
.symetrical
));
1502 Append(new BoolField
<1>(limit
.revert
));
1503 if (HAS_LARGE_LCD(board
)) {
1504 Append(new ZCharField
<6>(limit
.name
));
1506 if (IS_TARANIS(board
) && version
>= 216) {
1507 Append(new SignedField
<8>(limit
.curve
.value
));
1513 class CurvesField
: public TransformedField
{
1515 CurvesField(CurveData
* curves
, BoardEnum board
, unsigned int version
):
1516 TransformedField(internalField
),
1517 internalField("Curves"),
1521 maxCurves(MAX_CURVES(board
, version
)),
1522 maxPoints(IS_ARM(board
) ? 512 : 112-8)
1524 for (int i
=0; i
<maxCurves
; i
++) {
1525 if (IS_ARM(board
) && version
>= 218) {
1526 internalField
.Append(new UnsignedField
<1>((unsigned int &)curves
[i
].type
));
1527 internalField
.Append(new BoolField
<1>(curves
[i
].smooth
));
1528 internalField
.Append(new ConversionField
< SignedField
<6> >(curves
[i
].count
, -5));
1529 internalField
.Append(new ZCharField
<3>(curves
[i
].name
));
1531 else if (IS_TARANIS(board
) && version
>= 216) {
1532 internalField
.Append(new UnsignedField
<3>((unsigned int &)curves
[i
].type
));
1533 internalField
.Append(new BoolField
<1>(curves
[i
].smooth
));
1534 internalField
.Append(new SpareBitsField
<4>());
1535 internalField
.Append(new ConversionField
< SignedField
<8> >(curves
[i
].count
, -5));
1537 else if (IS_ARM(board
)) {
1538 internalField
.Append(new SignedField
<16>(_curves
[i
]));
1541 internalField
.Append(new SignedField
<8>(_curves
[i
]));
1545 for (int i
=0; i
<maxPoints
; i
++) {
1546 internalField
.Append(new SignedField
<8>(_points
[i
]));
1550 virtual void beforeExport()
1552 memset(_points
, 0, sizeof(_points
));
1554 int * cur
= &_points
[0];
1557 for (int i
=0; i
<maxCurves
; i
++) {
1558 CurveData
*curve
= &curves
[i
];
1559 if (IS_STM32(board
) && version
>= 216) {
1560 offset
+= (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
? curve
->count
* 2 - 2 : curve
->count
);
1561 if (offset
> maxPoints
) {
1562 EEPROMWarnings
.push_back(::QObject::tr("OpenTX only accepts %1 points in all curves").arg(maxPoints
));
1567 offset
+= (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
? curve
->count
* 2 - 2 : curve
->count
) - 5;
1568 if (offset
> maxPoints
- 5 * maxCurves
) {
1569 EEPROMWarnings
.push_back(::QObject::tr("OpenTx only accepts %1 points in all curves").arg(maxPoints
));
1572 _curves
[i
] = offset
;
1574 for (int j
=0; j
<curve
->count
; j
++) {
1575 *cur
++ = curve
->points
[j
].y
;
1577 if (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
) {
1578 for (int j
=1; j
<curve
->count
-1; j
++) {
1579 *cur
++ = curve
->points
[j
].x
;
1585 virtual void afterImport()
1587 int * cur
= &_points
[0];
1589 for (int i
=0; i
<maxCurves
; i
++) {
1590 CurveData
* curve
= &curves
[i
];
1591 if (!IS_STM32(board
) || version
< 216) {
1592 int * next
= &_points
[5*(i
+1) + _curves
[i
]];
1593 int size
= next
- cur
;
1594 if (size
% 2 == 0) {
1595 curve
->count
= (size
/ 2) + 1;
1596 curve
->type
= CurveData::CURVE_TYPE_CUSTOM
;
1599 curve
->count
= size
;
1600 curve
->type
= CurveData::CURVE_TYPE_STANDARD
;
1604 if (curve
->count
> 17) {
1605 qDebug() << "Wrong points count" << curve
->count
;
1607 for (int j
=0; j
<maxCurves
; j
++) {
1608 CurveData
*curve
= &curves
[j
];
1614 for (int j
=0; j
<curve
->count
; j
++) {
1615 curve
->points
[j
].y
= *cur
++;
1618 if (curve
->type
== CurveData::CURVE_TYPE_CUSTOM
) {
1619 curve
->points
[0].x
= -100;
1620 for (int j
=1; j
<curve
->count
-1; j
++)
1621 curve
->points
[j
].x
= *cur
++;
1622 curve
->points
[curve
->count
-1].x
= +100;
1625 for (int j
=0; j
<curve
->count
; j
++)
1626 curve
->points
[j
].x
= -100 + (200*i
) / (curve
->count
-1);
1628 eepromImportDebug() << QString("imported curve: %3 points").arg(curve
->count
);
1633 StructField internalField
;
1636 unsigned int version
;
1639 int _curves
[CPN_MAX_CURVES
];
1640 int _points
[CPN_MAX_CURVES
*CPN_MAX_POINTS
*2];
1643 class LogicalSwitchesFunctionsTable
: public ConversionTable
{
1646 LogicalSwitchesFunctionsTable(BoardEnum board
, unsigned int version
)
1649 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
1650 addConversion(LS_FN_OFF
, val
++);
1651 if (IS_ARM(board
) && version
>= 216)
1652 addConversion(LS_FN_VEQUAL
, val
++);
1653 if (afterrelease21March2013
)
1654 addConversion(LS_FN_VALMOSTEQUAL
, val
++);
1655 addConversion(LS_FN_VPOS
, val
++);
1656 addConversion(LS_FN_VNEG
, val
++);
1657 if (IS_ARM(board
) && version
>= 216) val
++; // later RANGE
1658 addConversion(LS_FN_APOS
, val
++);
1659 addConversion(LS_FN_ANEG
, val
++);
1660 addConversion(LS_FN_AND
, val
++);
1661 addConversion(LS_FN_OR
, val
++);
1662 addConversion(LS_FN_XOR
, val
++);
1663 if (IS_ARM(board
) && version
>= 216) addConversion(LS_FN_EDGE
, val
++);
1664 addConversion(LS_FN_EQUAL
, val
++);
1665 if (!afterrelease21March2013
)
1666 addConversion(LS_FN_NEQUAL
, val
++);
1667 addConversion(LS_FN_GREATER
, val
++);
1668 addConversion(LS_FN_LESS
, val
++);
1669 if (!afterrelease21March2013
) {
1670 addConversion(LS_FN_EGREATER
, val
++);
1671 addConversion(LS_FN_ELESS
, val
++);
1673 addConversion(LS_FN_DPOS
, val
++);
1674 addConversion(LS_FN_DAPOS
, val
++);
1675 addConversion(LS_FN_TIMER
, val
++);
1677 addConversion(LS_FN_STICKY
, val
++);
1681 class AndSwitchesConversionTable
: public ConversionTable
{
1684 AndSwitchesConversionTable(BoardEnum board
, unsigned int version
)
1687 addConversion(RawSwitch(SWITCH_TYPE_NONE
), val
++);
1689 if (IS_STM32(board
)) {
1690 for (int i
=1; i
<=MAX_SWITCHES_POSITION(board
, version
); i
++) {
1691 int s
= switchIndex(i
, board
, version
);
1692 if (IS_TARANIS(board
) && version
< 217) {
1693 // SF positions 16 and 17 => 16 and 18
1694 // SH positions 21 and 22 => 22 and 24
1695 if (s
== 17 || s
== 23) {
1699 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
);
1700 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
1702 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
1703 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, -i
), -val
);
1704 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
1707 else if (IS_SKY9X(board
)) {
1708 for (int i
=1; i
<=8; i
++) {
1709 int s
= switchIndex(i
, board
, version
);
1710 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, -s
), -val
);
1711 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
1713 for (int i
=1; i
<=MAX_LOGICAL_SWITCHES(board
, version
); i
++) {
1714 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, -i
), -val
);
1715 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
1719 for (int i
=1; i
<=9; i
++) {
1720 int s
= switchIndex(i
, board
, version
);
1721 addConversion(RawSwitch(SWITCH_TYPE_SWITCH
, s
), val
++);
1723 for (int i
=1; i
<=7; i
++) {
1724 addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL
, i
), val
++);
1729 static ConversionTable
* getInstance(BoardEnum board
, unsigned int version
)
1731 if (IS_ARM(board
) && version
>= 216)
1732 return new SwitchesConversionTable(board
, version
);
1734 return new AndSwitchesConversionTable(board
, version
);
1737 static std::list
<Cache
> internalCache
;
1739 for (std::list
<Cache
>::iterator it
=internalCache
.begin(); it
!=internalCache
.end(); it
++) {
1740 Cache element
= *it
;
1741 if (element
.board
== board
&& element
.version
== version
&& element
.flags
== flags
)
1742 return element
.table
;
1745 Cache
element(board
, version
, flags
, new SwitchesConversionTable(board
, version
, flags
));
1746 internalCache
.push_back(element
);
1747 return element
.table
;
1754 void addConversion(const RawSwitch
& sw
, const int b
)
1756 ConversionTable::addConversion(sw
.toValue(), b
);
1760 class LogicalSwitchField
: public TransformedField
{
1762 LogicalSwitchField(LogicalSwitchData
& csw
, BoardEnum board
, unsigned int version
, unsigned int variant
, ModelData
* model
=NULL
):
1763 TransformedField(internalField
),
1764 internalField("LogicalSwitch"),
1770 functionsConversionTable(board
, version
),
1771 sourcesConversionTable(SourcesConversionTable::getInstance(board
, version
, variant
, (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) ? 0 : FLAG_NOSWITCHES
)),
1772 switchesConversionTable(SwitchesConversionTable::getInstance(board
, version
)),
1773 andswitchesConversionTable(AndSwitchesConversionTable::getInstance(board
, version
)),
1778 if (IS_ARM(board
) && version
>= 218) {
1779 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.func
, &functionsConversionTable
, "Function"));
1780 internalField
.Append(new SignedField
<10>(v1
));
1781 internalField
.Append(new SignedField
<10>(v3
));
1782 internalField
.Append(new ConversionField
< SignedField
<9> >((int &)csw
.andsw
, andswitchesConversionTable
, "AND switch"));
1783 internalField
.Append(new SpareBitsField
<1>()); // TODO extra switch mode
1784 internalField
.Append(new SpareBitsField
<2>());
1785 internalField
.Append(new SignedField
<16>(v2
));
1787 else if (IS_ARM(board
) && version
>= 217) {
1788 internalField
.Append(new ConversionField
< UnsignedField
<6> >(csw
.func
, &functionsConversionTable
, "Function"));
1789 internalField
.Append(new SignedField
<10>(v1
));
1790 internalField
.Append(new SignedField
<16>(v2
));
1791 internalField
.Append(new SignedField
<16>(v3
));
1793 else if (IS_ARM(board
) && version
>= 216) {
1794 internalField
.Append(new SignedField
<8>(v1
));
1795 internalField
.Append(new SignedField
<16>(v2
));
1796 internalField
.Append(new SignedField
<16>(v3
));
1797 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.func
, &functionsConversionTable
, "Function"));
1799 else if (IS_ARM(board
) && version
>= 215) {
1800 internalField
.Append(new SignedField
<16>(v1
));
1801 internalField
.Append(new SignedField
<16>(v2
));
1802 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.func
, &functionsConversionTable
, "Function"));
1804 else if (IS_ARM(board
)) {
1805 internalField
.Append(new SignedField
<8>(v1
));
1806 internalField
.Append(new SignedField
<8>(v2
));
1807 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.func
, &functionsConversionTable
, "Function"));
1810 internalField
.Append(new SignedField
<8>(v1
));
1811 internalField
.Append(new SignedField
<8>(v2
));
1813 internalField
.Append(new ConversionField
< UnsignedField
<4> >(csw
.func
, &functionsConversionTable
, "Function"));
1815 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.func
, &functionsConversionTable
, "Function"));
1818 if (IS_ARM(board
)) {
1819 int scale
= (version
>= 216 ? 0 : 5);
1820 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.delay
, 0, scale
));
1821 internalField
.Append(new ConversionField
< UnsignedField
<8> >(csw
.duration
, 0, scale
));
1822 if (version
>= 214 && version
<= 217) {
1823 internalField
.Append(new ConversionField
< SignedField
<8> >((int &)csw
.andsw
, andswitchesConversionTable
, "AND switch"));
1827 if (version
>= 213) {
1828 internalField
.Append(new ConversionField
< UnsignedField
<4> >((unsigned int &)csw
.andsw
, andswitchesConversionTable
, "AND switch"));
1833 ~LogicalSwitchField()
1835 delete andswitchesConversionTable
;
1838 virtual void beforeExport()
1840 if (csw
.func
== LS_FN_TIMER
) {
1844 else if (csw
.func
== LS_FN_EDGE
) {
1845 switchesConversionTable
->exportValue(csw
.val1
, v1
);
1849 else if ((csw
.func
>= LS_FN_AND
&& csw
.func
<= LS_FN_XOR
) || csw
.func
== LS_FN_STICKY
) {
1850 switchesConversionTable
->exportValue(csw
.val1
, v1
);
1851 switchesConversionTable
->exportValue(csw
.val2
, v2
);
1853 else if (csw
.func
>= LS_FN_EQUAL
&& csw
.func
<= LS_FN_ELESS
) {
1854 sourcesConversionTable
->exportValue(csw
.val1
, v1
);
1855 sourcesConversionTable
->exportValue(csw
.val2
, v2
);
1857 else if (csw
.func
!= LS_FN_OFF
) {
1858 sourcesConversionTable
->exportValue(csw
.val1
, v1
);
1863 virtual void afterImport()
1865 if (csw
.func
== LS_FN_TIMER
) {
1869 else if (csw
.func
== LS_FN_EDGE
) {
1870 switchesConversionTable
->importValue(v1
, csw
.val1
);
1874 else if ((csw
.func
>= LS_FN_AND
&& csw
.func
<= LS_FN_XOR
) || csw
.func
== LS_FN_STICKY
) {
1875 switchesConversionTable
->importValue(v1
, csw
.val1
);
1876 switchesConversionTable
->importValue(v2
, csw
.val2
);
1878 else if (csw
.func
>= LS_FN_EQUAL
&& csw
.func
<= LS_FN_ELESS
) {
1879 if (IS_ARM(board
)) {
1880 sourcesConversionTable
->importValue((uint32_t)v1
, csw
.val1
);
1881 sourcesConversionTable
->importValue((uint32_t)v2
, csw
.val2
);
1884 sourcesConversionTable
->importValue((uint8_t)v1
, csw
.val1
);
1885 sourcesConversionTable
->importValue((uint8_t)v2
, csw
.val2
);
1887 if (IS_TARANIS(board
) && version
< 216) {
1888 RawSource
val1(csw
.val1
);
1889 if (val1
.type
== SOURCE_TYPE_STICK
&& val1
.index
< CPN_MAX_STICKS
) {
1890 csw
.val1
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, val1
.index
).toValue();
1892 RawSource
val2(csw
.val2
);
1893 if (val2
.type
== SOURCE_TYPE_STICK
&& val2
.index
< CPN_MAX_STICKS
) {
1894 csw
.val2
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, val2
.index
).toValue();
1898 else if (csw
.func
!= LS_FN_OFF
) {
1899 if (IS_ARM(board
) && version
>= 217) {
1900 sourcesConversionTable
->importValue((uint32_t)v1
, csw
.val1
);
1903 sourcesConversionTable
->importValue((uint8_t)v1
, csw
.val1
);
1905 if (IS_TARANIS(board
) && version
< 216) {
1906 RawSource
val1(csw
.val1
);
1907 if (val1
.type
== SOURCE_TYPE_STICK
&& val1
.index
< CPN_MAX_STICKS
) {
1908 csw
.val1
= RawSource(SOURCE_TYPE_VIRTUAL_INPUT
, val1
.index
).toValue();
1912 RawSource
val1(csw
.val1
);
1913 if (IS_ARM(board
) && version
< 216 && val1
.type
== SOURCE_TYPE_TELEMETRY
) {
1914 switch (val1
.index
) {
1915 case TELEMETRY_SOURCE_TIMER1
:
1916 case TELEMETRY_SOURCE_TIMER2
:
1917 case TELEMETRY_SOURCE_TIMER3
:
1918 csw
.val2
= (csw
.val2
+ 128) * 3;
1920 case TELEMETRY_SOURCE_ALT
:
1921 case TELEMETRY_SOURCE_GPS_ALT
:
1922 case TELEMETRY_SOURCE_ALT_MIN
:
1923 case TELEMETRY_SOURCE_ALT_MAX
:
1924 csw
.val2
= (csw
.val2
+ 128) * 8 - 500;
1926 case TELEMETRY_SOURCE_RPM
:
1927 case TELEMETRY_SOURCE_RPM_MAX
:
1928 csw
.val2
= (csw
.val2
+ 128) * 50;
1930 case TELEMETRY_SOURCE_T1
:
1931 case TELEMETRY_SOURCE_T2
:
1932 case TELEMETRY_SOURCE_T1_MAX
:
1933 case TELEMETRY_SOURCE_T2_MAX
:
1934 csw
.val2
= (csw
.val2
+ 128) + 30;
1936 case TELEMETRY_SOURCE_CELL
:
1937 case TELEMETRY_SOURCE_HDG
:
1938 csw
.val2
= (csw
.val2
+ 128) * 2;
1940 case TELEMETRY_SOURCE_DIST
:
1941 case TELEMETRY_SOURCE_DIST_MAX
:
1942 csw
.val2
= (csw
.val2
+ 128) * 8;
1944 case TELEMETRY_SOURCE_CURRENT
:
1945 case TELEMETRY_SOURCE_POWER
:
1946 csw
.val2
= (csw
.val2
+ 128) * 5;
1948 case TELEMETRY_SOURCE_CONSUMPTION
:
1949 csw
.val2
= (csw
.val2
+ 128) * 20;
1957 eepromImportDebug() << QString("imported %1: %2").arg(internalField
.getName()).arg(csw
.funcToString());
1961 StructField internalField
;
1962 LogicalSwitchData
& csw
;
1964 unsigned int version
;
1965 unsigned int variant
;
1967 LogicalSwitchesFunctionsTable functionsConversionTable
;
1968 SourcesConversionTable
* sourcesConversionTable
;
1969 SwitchesConversionTable
* switchesConversionTable
;
1970 ConversionTable
* andswitchesConversionTable
;
1976 class CustomFunctionsConversionTable
: public ConversionTable
{
1979 CustomFunctionsConversionTable(BoardEnum board
, unsigned int version
)
1983 if (version
>= 216) {
1984 for (int i
=0; i
<MAX_CHANNELS(board
, version
); i
++) {
1985 addConversion(i
, val
);
1989 else if (IS_ARM(board
) || version
< 213) {
1990 for (int i
=0; i
<16; i
++) {
1991 addConversion(val
, val
);
1996 for (int i
=0; i
<16; i
++) {
1997 addConversion(i
, i
/ 4);
2002 if (version
>= 216) {
2003 addConversion(FuncTrainer
, val
);
2004 addConversion(FuncTrainerRUD
, val
);
2005 addConversion(FuncTrainerELE
, val
);
2006 addConversion(FuncTrainerTHR
, val
);
2007 addConversion(FuncTrainerAIL
, val
);
2011 addConversion(FuncTrainer
, val
++);
2012 addConversion(FuncTrainerRUD
, val
++);
2013 addConversion(FuncTrainerELE
, val
++);
2014 addConversion(FuncTrainerTHR
, val
++);
2015 addConversion(FuncTrainerAIL
, val
++);
2018 addConversion(FuncInstantTrim
, val
++);
2020 if (version
>= 216) {
2021 addConversion(FuncReset
, val
++);
2022 if (IS_ARM(board
)) {
2023 addConversion(FuncSetTimer1
, val
);
2024 addConversion(FuncSetTimer2
, val
);
2025 addConversion(FuncSetTimer3
, val
);
2028 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++)
2029 addConversion(FuncAdjustGV1
+i
, val
);
2031 if (IS_ARM(board
)) {
2032 addConversion(FuncVolume
, val
++);
2033 addConversion(FuncSetFailsafeInternalModule
, val
);
2034 addConversion(FuncSetFailsafeExternalModule
, val
++);
2035 addConversion(FuncRangeCheckInternalModule
, val
);
2036 addConversion(FuncRangeCheckExternalModule
, val
++);
2037 addConversion(FuncBindInternalModule
, val
);
2038 addConversion(FuncBindExternalModule
, val
++);
2040 addConversion(FuncPlaySound
, val
++);
2041 addConversion(FuncPlayPrompt
, val
++);
2042 if (version
>= 213 && !IS_ARM(board
))
2043 addConversion(FuncPlayBoth
, val
++);
2044 addConversion(FuncPlayValue
, val
++);
2045 if (IS_ARM(board
)) {
2046 addConversion(FuncReserve
, val
++);
2047 if (IS_STM32(board
))
2048 addConversion(FuncPlayScript
, val
++);
2050 addConversion(FuncReserve
, val
++);
2051 addConversion(FuncReserve
, val
++);
2052 addConversion(FuncBackgroundMusic
, val
++);
2053 addConversion(FuncBackgroundMusicPause
, val
++);
2055 addConversion(FuncVario
, val
++);
2056 addConversion(FuncPlayHaptic
, val
++);
2057 if (IS_2560(board
) || IS_ARM(board
) )
2058 addConversion(FuncLogs
, val
++);
2059 addConversion(FuncBacklight
, val
++);
2060 if (IS_STM32(board
))
2061 addConversion(FuncScreenshot
, val
++);
2064 addConversion(FuncPlaySound
, val
++);
2065 if (!IS_TARANIS(board
))
2066 addConversion(FuncPlayHaptic
, val
++);
2067 addConversion(FuncReset
, val
++);
2068 addConversion(FuncVario
, val
++);
2069 addConversion(FuncPlayPrompt
, val
++);
2070 if (version
>= 213 && !IS_ARM(board
))
2071 addConversion(FuncPlayBoth
, val
++);
2072 addConversion(FuncPlayValue
, val
++);
2073 if (IS_2560(board
) || IS_ARM(board
) )
2074 addConversion(FuncLogs
, val
++);
2076 addConversion(FuncVolume
, val
++);
2077 addConversion(FuncBacklight
, val
++);
2078 if (IS_ARM(board
)) {
2079 addConversion(FuncBackgroundMusic
, val
++);
2080 addConversion(FuncBackgroundMusicPause
, val
++);
2082 for (int i
=0; i
<5; i
++)
2083 addConversion(FuncAdjustGV1
+i
, val
++);
2089 class SwitchesWarningField
: public TransformedField
{
2091 SwitchesWarningField(uint64_t & sw
, BoardEnum board
, unsigned int version
):
2092 TransformedField(internalField
),
2093 internalField(_sw
, "SwitchesWarning"),
2100 virtual void beforeExport()
2105 virtual void afterImport()
2107 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
2108 if (afterrelease21March2013
&& version
< 216) {
2111 else if (!afterrelease21March2013
) {
2112 sw
= ((_sw
& 0x30) >> 4) + ((_sw
& 0x0E) << 1) + ((_sw
& 0xC0) >> 1);
2117 eepromImportDebug() << QString("imported %1").arg(internalField
.getName());
2121 BaseUnsignedField
<uint64_t, N
> internalField
;
2125 unsigned int version
;
2128 class ArmCustomFunctionField
: public TransformedField
{
2130 ArmCustomFunctionField(CustomFunctionData
& fn
, BoardEnum board
, unsigned int version
, unsigned int variant
):
2131 TransformedField(internalField
),
2132 internalField("CustomFunction"),
2137 functionsConversionTable(board
, version
),
2138 sourcesConversionTable(SourcesConversionTable::getInstance(board
, version
, variant
, version
>= 216 ? 0 : FLAG_NONONE
)),
2143 memset(_param
, 0, sizeof(_param
));
2145 if (version
>= 218) {
2146 internalField
.Append(new SwitchField
<9>(fn
.swtch
, board
, version
));
2147 internalField
.Append(new ConversionField
< UnsignedField
<7> >(_func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2150 internalField
.Append(new SwitchField
<8>(fn
.swtch
, board
, version
));
2151 internalField
.Append(new ConversionField
< UnsignedField
<8> >(_func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2154 if (IS_TARANIS(board
) && version
>= 216)
2155 internalField
.Append(new CharField
<8>(_param
, false));
2156 else if (IS_TARANIS(board
))
2157 internalField
.Append(new CharField
<10>(_param
, false));
2159 internalField
.Append(new CharField
<6>(_param
, false));
2161 if (version
>= 216) {
2162 internalField
.Append(new SignedField
<8>(_active
));
2164 else if (version
>= 214) {
2165 internalField
.Append(new UnsignedField
<2>(_mode
));
2166 internalField
.Append(new UnsignedField
<6>((unsigned int &)_active
));
2169 internalField
.Append(new UnsignedField
<8>((unsigned int &)_active
));
2170 internalField
.Append(new SpareBitsField
<8>());
2174 static bool hasRepeatParam(const CustomFunctionData
& fn
)
2176 return (fn
.func
== FuncPlaySound
|| fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncPlayValue
|| fn
.func
== FuncPlayHaptic
);
2179 virtual void beforeExport()
2181 if (fn
.swtch
.type
!= SWITCH_TYPE_NONE
) {
2184 if (hasRepeatParam(fn
))
2185 _active
= (version
>= 216 ? fn
.repeatParam
: (fn
.repeatParam
/5));
2187 _active
= (fn
.enabled
? 1 : 0);
2189 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2190 if (version
>= 216) {
2191 *((uint16_t *)_param
) = fn
.param
;
2192 *((uint8_t *)(_param
+3)) = fn
.func
- FuncOverrideCH1
;
2195 *((uint32_t *)_param
) = fn
.param
;
2198 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2200 *((uint8_t *)(_param
+3)) = fn
.func
- FuncTrainer
;
2202 else if (fn
.func
>= FuncSetTimer1
&& fn
.func
<= FuncSetTimer3
) {
2203 if (version
>= 216) {
2204 *((uint16_t *)_param
) = fn
.param
;
2205 *((uint8_t *)(_param
+3)) = fn
.func
- FuncSetTimer1
;
2208 else if (fn
.func
>= FuncSetFailsafeInternalModule
&& fn
.func
<= FuncSetFailsafeExternalModule
) {
2209 if (version
>= 216) {
2210 *((uint16_t *)_param
) = fn
.func
- FuncSetFailsafeInternalModule
;
2213 else if (fn
.func
>= FuncRangeCheckInternalModule
&& fn
.func
<= FuncRangeCheckExternalModule
) {
2214 if (version
>= 216) {
2215 *((uint16_t *)_param
) = fn
.func
- FuncRangeCheckInternalModule
;
2218 else if (fn
.func
>= FuncBindInternalModule
&& fn
.func
<= FuncBindExternalModule
) {
2219 if (version
>= 216) {
2220 *((uint16_t *)_param
) = fn
.func
- FuncBindInternalModule
;
2223 else if (fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncBackgroundMusic
|| fn
.func
== FuncPlayScript
) {
2224 memcpy(_param
, fn
.paramarm
, sizeof(_param
));
2226 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2227 if (version
>= 216) {
2228 *((uint8_t *)(_param
+2)) = fn
.adjustMode
;
2229 *((uint8_t *)(_param
+3)) = fn
.func
- FuncAdjustGV1
;
2231 if (fn
.adjustMode
== 1)
2232 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2233 else if (fn
.adjustMode
== 2)
2234 value
= RawSource(fn
.param
).index
;
2237 *((uint16_t *)_param
) = value
;
2239 else if (version
>= 214) {
2241 _mode
= fn
.adjustMode
;
2242 if (fn
.adjustMode
== 1)
2243 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2244 else if (fn
.adjustMode
== 2)
2245 value
= RawSource(fn
.param
).index
;
2248 *((uint32_t *)_param
) = value
;
2252 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2253 *((uint32_t *)_param
) = value
;
2256 else if (fn
.func
== FuncPlayValue
|| fn
.func
== FuncVolume
) {
2258 sourcesConversionTable
->exportValue(fn
.param
, (int &)value
);
2260 *((uint16_t *)_param
) = value
;
2262 *((uint32_t *)_param
) = value
;
2264 else if (fn
.func
== FuncReset
) {
2266 *((uint32_t *)_param
) = fn
.param
;
2268 *((uint32_t *)_param
) = (fn
.param
< 2 ? fn
.param
: fn
.param
-1);
2271 *((uint32_t *)_param
) = fn
.param
;
2276 virtual void afterImport()
2278 fn
.func
= (AssignFunc
)_func
;
2280 if (hasRepeatParam(fn
))
2281 fn
.repeatParam
= (version
>= 216 ? _active
: (_active
*5));
2283 fn
.enabled
= (_active
& 0x01);
2285 unsigned int value
=0, mode
=0, index
=0;
2286 if (version
>= 216) {
2287 value
= *((uint16_t *)_param
);
2288 mode
= *((uint8_t *)(_param
+2));
2289 index
= *((uint8_t *)(_param
+3));
2292 value
= *((uint32_t *)_param
);
2295 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2296 fn
.func
= AssignFunc(fn
.func
+ index
);
2297 fn
.param
= (int16_t)(uint16_t)value
;
2299 else if (fn
.func
>= FuncSetTimer1
&& fn
.func
<= FuncSetTimer3
) {
2300 fn
.func
= AssignFunc(fn
.func
+ index
);
2301 fn
.param
= (int)value
;
2303 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2304 fn
.func
= AssignFunc(fn
.func
+ index
);
2307 else if (fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncBackgroundMusic
|| fn
.func
== FuncPlayScript
) {
2308 memcpy(fn
.paramarm
, _param
, sizeof(fn
.paramarm
));
2310 else if (fn
.func
== FuncVolume
) {
2311 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2313 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2314 if (version
>= 216) {
2315 fn
.func
= AssignFunc(fn
.func
+ index
);
2316 fn
.adjustMode
= mode
;
2317 if (fn
.adjustMode
== 1)
2318 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2319 else if (fn
.adjustMode
== 2)
2320 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, value
).toValue();
2322 fn
.param
= (int16_t)value
;
2324 else if (version
>= 214) {
2325 fn
.adjustMode
= _mode
;
2326 if (fn
.adjustMode
== 1)
2327 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2328 else if (fn
.adjustMode
== 2)
2329 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, value
).toValue();
2331 fn
.param
= (int8_t)value
;
2334 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2337 else if (fn
.func
== FuncPlayValue
) {
2339 sourcesConversionTable
->importValue(value
, (int &)fn
.param
);
2341 SourcesConversionTable::getInstance(board
, version
, variant
, FLAG_NONONE
|FLAG_NOSWITCHES
)->importValue(value
, (int &)fn
.param
);
2343 else if (fn
.func
== FuncReset
) {
2347 fn
.param
= (value
< 2 ? value
: value
+1);
2352 eepromImportDebug() << QString("imported %1").arg(internalField
.getName());
2356 StructField internalField
;
2357 CustomFunctionData
& fn
;
2359 unsigned int version
;
2360 unsigned int variant
;
2361 CustomFunctionsConversionTable functionsConversionTable
;
2362 SourcesConversionTable
* sourcesConversionTable
;
2369 class AvrCustomFunctionField
: public TransformedField
{
2371 AvrCustomFunctionField(CustomFunctionData
& fn
, BoardEnum board
, unsigned int version
, unsigned int variant
):
2372 TransformedField(internalField
),
2373 internalField("CustomFunction"),
2378 functionsConversionTable(board
, version
),
2379 sourcesConversionTable(SourcesConversionTable::getInstance(board
, version
, variant
, version
>= 216 ? 0 : FLAG_NONONE
)),
2385 if (version
>= 217 && IS_2560(board
)) {
2386 internalField
.Append(new SwitchField
<8>(fn
.swtch
, board
, version
));
2387 internalField
.Append(new ConversionField
< UnsignedField
<8> >((unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2388 internalField
.Append(new UnsignedField
<2>(fn
.adjustMode
));
2389 internalField
.Append(new UnsignedField
<4>(_union_param
));
2390 internalField
.Append(new UnsignedField
<1>(_active
));
2391 internalField
.Append(new SpareBitsField
<1>());
2393 else if (version
>= 216) {
2394 internalField
.Append(new SwitchField
<6>(fn
.swtch
, board
, version
));
2395 internalField
.Append(new ConversionField
< UnsignedField
<4> >((unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2396 internalField
.Append(new UnsignedField
<5>(_union_param
));
2397 internalField
.Append(new UnsignedField
<1>(_active
));
2399 else if (version
>= 213) {
2400 internalField
.Append(new SwitchField
<8>(fn
.swtch
, board
, version
));
2401 internalField
.Append(new UnsignedField
<3>(_union_param
));
2402 internalField
.Append(new ConversionField
< UnsignedField
<5> >((unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2405 internalField
.Append(new SwitchField
<8>(fn
.swtch
, board
, version
));
2406 internalField
.Append(new ConversionField
< UnsignedField
<7> >((unsigned int &)fn
.func
, &functionsConversionTable
, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
2407 internalField
.Append(new BoolField
<1>((bool &)fn
.enabled
));
2409 internalField
.Append(new UnsignedField
<8>(_param
));
2412 virtual void beforeExport()
2415 _active
= (fn
.enabled
? 1 : 0);
2417 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2419 _union_param
= fn
.func
- FuncOverrideCH1
;
2420 else if (version
>= 213)
2421 _active
+= ((fn
.func
% 4) << 1);
2423 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2425 _union_param
= fn
.func
- FuncTrainer
;
2427 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2428 if (version
>= 217 && IS_2560(board
)) {
2429 _union_param
= (fn
.func
- FuncAdjustGV1
);
2430 if (fn
.adjustMode
== 1)
2431 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2432 else if (fn
.adjustMode
== 2)
2433 _param
= RawSource(fn
.param
).index
;
2435 else if (version
>= 216) {
2436 _union_param
= fn
.adjustMode
;
2437 _union_param
+= (fn
.func
- FuncAdjustGV1
) << 2;
2438 if (fn
.adjustMode
== 1)
2439 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2440 else if (fn
.adjustMode
== 2)
2441 _param
= RawSource(fn
.param
).index
;
2443 else if (version
>= 213) {
2444 _active
+= (fn
.adjustMode
<< 1);
2445 if (fn
.adjustMode
== 1)
2446 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2447 else if (fn
.adjustMode
== 2)
2448 _param
= RawSource(fn
.param
).index
;
2451 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2454 else if (fn
.func
== FuncPlayValue
) {
2455 if (version
>= 216) {
2456 _union_param
= fn
.repeatParam
/ 10;
2457 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2459 else if (version
>= 213) {
2460 _active
= fn
.repeatParam
/ 10;
2461 sourcesConversionTable
->exportValue(fn
.param
, (int &)_param
);
2464 SourcesConversionTable::getInstance(board
, version
, variant
, FLAG_NONONE
|FLAG_NOSWITCHES
)->exportValue(fn
.param
, (int &)_param
);
2467 else if (fn
.func
== FuncPlaySound
|| fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncPlayBoth
) {
2468 if (version
>= 216) {
2469 _union_param
= fn
.repeatParam
/ 10;
2471 else if (version
>= 213) {
2472 _active
= fn
.repeatParam
/ 10;
2477 virtual void afterImport()
2480 if (version
>= 213) {
2481 fn
.enabled
= (_active
& 0x01);
2484 if (fn
.func
>= FuncOverrideCH1
&& fn
.func
<= FuncOverrideCH32
) {
2486 fn
.func
= AssignFunc(fn
.func
+ _union_param
);
2487 else if (version
>= 213)
2488 fn
.func
= AssignFunc(((fn
.func
>> 2) << 2) + ((_active
>> 1) & 0x03));
2489 fn
.param
= (int8_t)fn
.param
;
2491 else if (fn
.func
>= FuncTrainer
&& fn
.func
<= FuncTrainerAIL
) {
2493 fn
.func
= AssignFunc(fn
.func
+ _union_param
);
2495 else if (fn
.func
>= FuncAdjustGV1
&& fn
.func
<= FuncAdjustGVLast
) {
2496 if (version
>= 217 && IS_2560(board
)) {
2497 fn
.func
= AssignFunc(fn
.func
+ _union_param
);
2498 if (fn
.adjustMode
== 1)
2499 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2500 else if (fn
.adjustMode
== 2)
2501 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, _param
).toValue();
2503 else if (version
>= 216) {
2504 fn
.func
= AssignFunc(fn
.func
+ (_union_param
>> 2));
2505 fn
.adjustMode
= (_union_param
& 0x03);
2506 if (fn
.adjustMode
== 1)
2507 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2508 else if (fn
.adjustMode
== 2)
2509 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, _param
).toValue();
2511 else if (version
>= 213) {
2512 fn
.adjustMode
= ((_active
>> 1) & 0x03);
2513 if (fn
.adjustMode
== 1)
2514 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2515 else if (fn
.adjustMode
== 2)
2516 fn
.param
= RawSource(SOURCE_TYPE_GVAR
, _param
).toValue();
2519 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2522 else if (fn
.func
== FuncPlayValue
) {
2523 if (version
>= 216) {
2524 fn
.repeatParam
= _union_param
* 10;
2525 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2527 else if (version
>= 213) {
2528 fn
.repeatParam
= _active
* 10;
2529 sourcesConversionTable
->importValue(_param
, (int &)fn
.param
);
2532 SourcesConversionTable::getInstance(board
, version
, variant
, FLAG_NONONE
|FLAG_NOSWITCHES
)->importValue(_param
, (int &)fn
.param
);
2535 else if (fn
.func
== FuncPlaySound
|| fn
.func
== FuncPlayPrompt
|| fn
.func
== FuncPlayBoth
) {
2537 fn
.repeatParam
= _union_param
* 10;
2538 else if (version
>= 213)
2539 fn
.repeatParam
= _active
* 10;
2541 eepromImportDebug() << QString("imported %1").arg(internalField
.getName());
2545 StructField internalField
;
2546 CustomFunctionData
& fn
;
2548 unsigned int version
;
2549 unsigned int variant
;
2550 CustomFunctionsConversionTable functionsConversionTable
;
2551 SourcesConversionTable
* sourcesConversionTable
;
2552 unsigned int _param
;
2554 unsigned int _union_param
;
2555 unsigned int _active
;
2558 class FrskyScreenField
: public DataField
{
2560 FrskyScreenField(FrSkyScreenData
& screen
, BoardEnum board
, unsigned int version
, unsigned int variant
):
2561 DataField("Frsky Screen"),
2566 for (int i
=0; i
<4; i
++) {
2567 if (IS_ARM(board
) && version
>= 217) {
2568 if (IS_TARANIS(board
))
2569 bars
.Append(new SourceField
<16>(screen
.body
.bars
[i
].source
, board
, version
, variant
));
2571 bars
.Append(new SourceField
<8>(screen
.body
.bars
[i
].source
, board
, version
, variant
));
2572 bars
.Append(new UnsignedField
<16>(screen
.body
.bars
[i
].barMin
));
2573 bars
.Append(new UnsignedField
<16>(screen
.body
.bars
[i
].barMax
));
2576 bars
.Append(new TelemetrySourceField
<8>(screen
.body
.bars
[i
].source
, board
, version
));
2577 bars
.Append(new UnsignedField
<8>(screen
.body
.bars
[i
].barMin
));
2578 bars
.Append(new UnsignedField
<8>(screen
.body
.bars
[i
].barMax
));
2582 int columns
= (HAS_LARGE_LCD(board
) ? 3 : 2);
2583 for (int i
=0; i
<4; i
++) {
2584 for (int j
=0; j
<columns
; j
++) {
2585 if (IS_TARANIS(board
) && version
>= 217)
2586 numbers
.Append(new SourceField
<16>(screen
.body
.lines
[i
].source
[j
], board
, version
, variant
));
2587 else if (IS_ARM(board
) && version
>= 217)
2588 numbers
.Append(new SourceField
<8>(screen
.body
.lines
[i
].source
[j
], board
, version
, variant
));
2590 numbers
.Append(new TelemetrySourceField
<8>(screen
.body
.lines
[i
].source
[j
], board
, version
));
2594 if (!IS_TARANIS(board
)) {
2596 numbers
.Append(new SpareBitsField
<12*8>());
2598 numbers
.Append(new SpareBitsField
<4*8>());
2601 if (IS_TARANIS(board
) && version
>= 217) {
2602 script
.Append(new CharField
<8>(screen
.body
.script
.filename
, true, "Script name"));
2603 script
.Append(new SpareBitsField
<16*8>());
2606 if (IS_ARM(board
) && version
>= 217) {
2607 if (IS_TARANIS(board
))
2608 none
.Append(new SpareBitsField
<24*8>());
2610 none
.Append(new SpareBitsField
<20*8>());
2614 virtual void ExportBits(QBitArray
& output
)
2616 if (IS_ARM(board
) && version
>= 217) {
2617 if (screen
.type
== TELEMETRY_SCREEN_SCRIPT
)
2618 script
.ExportBits(output
);
2619 else if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2620 numbers
.ExportBits(output
);
2621 else if (screen
.type
== TELEMETRY_SCREEN_BARS
)
2622 bars
.ExportBits(output
);
2624 none
.ExportBits(output
);
2627 if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2628 numbers
.ExportBits(output
);
2630 bars
.ExportBits(output
);
2634 virtual void ImportBits(const QBitArray
& input
)
2636 eepromImportDebug() << QString("importing %1: type: %2").arg(name
).arg(screen
.type
);
2638 // NOTA: screen.type should have been imported first!
2639 if (IS_ARM(board
) && version
>= 217) {
2640 if (screen
.type
== TELEMETRY_SCREEN_SCRIPT
)
2641 script
.ImportBits(input
);
2642 else if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2643 numbers
.ImportBits(input
);
2644 else if (screen
.type
== TELEMETRY_SCREEN_BARS
)
2645 bars
.ImportBits(input
);
2647 none
.ImportBits(input
);
2650 if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2651 numbers
.ImportBits(input
);
2653 bars
.ImportBits(input
);
2657 virtual unsigned int size()
2659 // NOTA: screen.type should have been imported first!
2660 if (IS_ARM(board
) && version
>= 217) {
2661 if (screen
.type
== TELEMETRY_SCREEN_SCRIPT
)
2662 return script
.size();
2663 else if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2664 return numbers
.size();
2665 else if (screen
.type
== TELEMETRY_SCREEN_BARS
)
2671 if (screen
.type
== TELEMETRY_SCREEN_NUMBERS
)
2672 return numbers
.size();
2679 FrSkyScreenData
& screen
;
2681 unsigned int version
;
2684 StructField numbers
;
2688 class RSSIConversionTable
: public ConversionTable
2691 RSSIConversionTable(int index
)
2693 addConversion(0, 2-index
);
2694 addConversion(1, 3-index
);
2695 addConversion(2, index
? 3 : 0);
2696 addConversion(3, 1-index
);
2699 RSSIConversionTable()
2704 class TelemetryVarioSourceConversionTable
: public ConversionTable
2707 TelemetryVarioSourceConversionTable(BoardEnum board
, unsigned int version
)
2710 if (!IS_TARANIS(board
)) {
2711 addConversion(TELEMETRY_VARIO_SOURCE_ALTI
, val
++);
2712 addConversion(TELEMETRY_VARIO_SOURCE_ALTI_PLUS
, val
++);
2714 addConversion(TELEMETRY_VARIO_SOURCE_VSPEED
, val
++);
2715 addConversion(TELEMETRY_VARIO_SOURCE_A1
, val
++);
2716 addConversion(TELEMETRY_VARIO_SOURCE_A2
, val
++);
2717 if (IS_TARANIS(board
)) {
2718 addConversion(TELEMETRY_VARIO_SOURCE_DTE
, val
++);
2723 class TelemetryVoltsSourceConversionTable
: public ConversionTable
2726 TelemetryVoltsSourceConversionTable(BoardEnum board
, unsigned int version
)
2729 addConversion(TELEMETRY_VOLTS_SOURCE_A1
, val
++);
2730 addConversion(TELEMETRY_VOLTS_SOURCE_A2
, val
++);
2731 if (IS_ARM(board
) && version
>= 216) {
2732 addConversion(TELEMETRY_VOLTS_SOURCE_A3
, val
++);
2733 addConversion(TELEMETRY_VOLTS_SOURCE_A4
, val
++);
2735 addConversion(TELEMETRY_VOLTS_SOURCE_FAS
, val
++);
2736 addConversion(TELEMETRY_VOLTS_SOURCE_CELLS
, val
++);
2740 class ScreenTypesConversionTable
: public ConversionTable
2743 ScreenTypesConversionTable(BoardEnum board
, unsigned int version
)
2746 if (IS_ARM(board
)) {
2747 addConversion(TELEMETRY_SCREEN_NONE
, val
++);
2749 addConversion(TELEMETRY_SCREEN_NUMBERS
, val
++);
2750 addConversion(TELEMETRY_SCREEN_BARS
, val
++);
2754 class TelemetryCurrentSourceConversionTable
: public ConversionTable
2757 TelemetryCurrentSourceConversionTable(BoardEnum board
, unsigned int version
)
2760 addConversion(TELEMETRY_CURRENT_SOURCE_NONE
, val
++);
2761 addConversion(TELEMETRY_CURRENT_SOURCE_A1
, val
++);
2762 addConversion(TELEMETRY_CURRENT_SOURCE_A2
, val
++);
2763 if (IS_ARM(board
) && version
>= 216) {
2764 addConversion(TELEMETRY_CURRENT_SOURCE_A3
, val
++);
2765 addConversion(TELEMETRY_CURRENT_SOURCE_A4
, val
++);
2767 addConversion(TELEMETRY_CURRENT_SOURCE_FAS
, val
++);
2771 class FrskyField
: public StructField
{
2773 FrskyField(FrSkyData
& frsky
, BoardEnum board
, unsigned int version
, unsigned int variant
):
2774 StructField("FrSky"),
2775 telemetryVarioSourceConversionTable(board
, version
),
2776 screenTypesConversionTable(board
, version
),
2777 telemetryVoltsSourceConversionTable(board
, version
),
2778 telemetryCurrentSourceConversionTable(board
, version
)
2780 rssiConversionTable
[0] = RSSIConversionTable(0);
2781 rssiConversionTable
[1] = RSSIConversionTable(1);
2783 if (IS_ARM(board
)) {
2784 if (!IS_HORUS(board
)) {
2785 if (version
>= 217) {
2786 Append(new UnsignedField
<8>(frsky
.voltsSource
, "Volts Source"));
2787 Append(new UnsignedField
<8>(frsky
.altitudeSource
, "Altitude Source"));
2790 for (int i
= 0; i
< (version
>= 216 ? 4 : 2); i
++) {
2791 Append(new UnsignedField
<8>(frsky
.channels
[i
].ratio
, "Ratio"));
2792 Append(new SignedField
<12>(frsky
.channels
[i
].offset
, "Offset"));
2793 Append(new UnsignedField
<4>(frsky
.channels
[i
].type
, "Type"));
2794 for (int j
= 0; j
< 2; j
++)
2795 Append(new UnsignedField
<8>(frsky
.channels
[i
].alarms
[j
].value
, "Alarm value"));
2796 for (int j
= 0; j
< 2; j
++)
2797 Append(new UnsignedField
<2>(frsky
.channels
[i
].alarms
[j
].level
));
2798 for (int j
= 0; j
< 2; j
++)
2799 Append(new UnsignedField
<1>(frsky
.channels
[i
].alarms
[j
].greater
));
2800 Append(new SpareBitsField
<2>());
2801 Append(new UnsignedField
<8>(frsky
.channels
[i
].multiplier
, 0, 5, "Multiplier"));
2803 Append(new UnsignedField
<8>(frsky
.usrProto
));
2804 if (version
>= 216) {
2805 Append(new ConversionField
<UnsignedField
<7> >(frsky
.voltsSource
, &telemetryVoltsSourceConversionTable
, "Volts Source"));
2806 Append(new SpareBitsField
<1>());
2809 Append(new ConversionField
<UnsignedField
<8> >(frsky
.voltsSource
, &telemetryVoltsSourceConversionTable
, "Volts Source"));
2811 Append(new ConversionField
<SignedField
<8> >(frsky
.blades
, -2));
2812 Append(new ConversionField
<UnsignedField
<8> >(frsky
.currentSource
, &telemetryCurrentSourceConversionTable
, "Current Source"));
2815 if (version
>= 217) {
2816 for (int i
= 0; i
< 4; i
++) {
2817 Append(new UnsignedField
<2>(frsky
.screens
[i
].type
));
2819 for (int i
= 0; i
< 4; i
++) {
2820 Append(new FrskyScreenField(frsky
.screens
[i
], board
, version
, variant
));
2824 Append(new UnsignedField
<1>(frsky
.screens
[0].type
));
2825 Append(new UnsignedField
<1>(frsky
.screens
[1].type
));
2826 Append(new UnsignedField
<1>(frsky
.screens
[2].type
));
2827 Append(new SpareBitsField
<5>());
2828 for (int i
= 0; i
< 3; i
++) {
2829 Append(new FrskyScreenField(frsky
.screens
[i
], board
, version
, variant
));
2834 if (version
>= 217) {
2835 Append(new UnsignedField
<7>(frsky
.varioSource
, "Vario Source"));
2836 Append(new BoolField
<1>(frsky
.varioCenterSilent
));
2839 Append(new ConversionField
< UnsignedField
<8> >(frsky
.varioSource
, &telemetryVarioSourceConversionTable
, "Vario Source"));
2841 Append(new SignedField
<8>(frsky
.varioCenterMax
));
2842 Append(new SignedField
<8>(frsky
.varioCenterMin
));
2843 Append(new SignedField
<8>(frsky
.varioMin
));
2844 Append(new SignedField
<8>(frsky
.varioMax
));
2845 for (int i
=0; i
<2; i
++) {
2846 Append(new ConversionField
< UnsignedField
<2> >(frsky
.rssiAlarms
[i
].level
, &rssiConversionTable
[i
], "RSSI"));
2847 Append(new ConversionField
< SignedField
<6> >(frsky
.rssiAlarms
[i
].value
, -45+i
*3));
2849 if (version
== 216) {
2850 Append(new BoolField
<1>(frsky
.mAhPersistent
));
2851 Append(new UnsignedField
<15>(frsky
.storedMah
));
2852 Append(new SignedField
<8>(frsky
.fasOffset
));
2856 for (int i
=0; i
<2; i
++) {
2857 Append(new UnsignedField
<8>(frsky
.channels
[i
].ratio
, "Ratio"));
2858 Append(new SignedField
<12>(frsky
.channels
[i
].offset
, "Offset"));
2859 Append(new UnsignedField
<4>(frsky
.channels
[i
].type
, "Type"));
2860 for (int j
=0; j
<2; j
++)
2861 Append(new UnsignedField
<8>(frsky
.channels
[i
].alarms
[j
].value
, "Alarm value"));
2862 for (int j
=0; j
<2; j
++)
2863 Append(new UnsignedField
<2>(frsky
.channels
[i
].alarms
[j
].level
));
2864 for (int j
=0; j
<2; j
++)
2865 Append(new UnsignedField
<1>(frsky
.channels
[i
].alarms
[j
].greater
));
2866 Append(new UnsignedField
<2>(frsky
.channels
[i
].multiplier
, 0, 3, "Multiplier"));
2868 Append(new UnsignedField
<2>(frsky
.usrProto
, "USR Proto"));
2869 Append(new ConversionField
< UnsignedField
<2> >((unsigned int &)frsky
.blades
, -2));
2870 for (int i
=0; i
<2; i
++) {
2871 Append(new ConversionField
< UnsignedField
<1> >(frsky
.screens
[i
].type
, &screenTypesConversionTable
, "Screen Type"));
2873 Append(new ConversionField
< UnsignedField
<2> >(frsky
.voltsSource
, &telemetryVoltsSourceConversionTable
, "Volts Source"));
2874 Append(new SignedField
<4>(frsky
.varioMin
, "Vario Min"));
2875 Append(new SignedField
<4>(frsky
.varioMax
));
2876 for (int i
=0; i
<2; i
++) {
2877 Append(new ConversionField
< UnsignedField
<2> >(frsky
.rssiAlarms
[i
].level
, &rssiConversionTable
[i
], "RSSI level"));
2878 Append(new ConversionField
< SignedField
<6> >(frsky
.rssiAlarms
[i
].value
, -45+i
*3, 0, 0, 100, "RSSI value"));
2880 for (int i
=0; i
<2; i
++) {
2881 Append(new FrskyScreenField(frsky
.screens
[i
], board
, version
, variant
));
2883 Append(new UnsignedField
<3>(frsky
.varioSource
));
2884 Append(new SignedField
<5>(frsky
.varioCenterMin
));
2885 Append(new ConversionField
< UnsignedField
<3> >(frsky
.currentSource
, &telemetryCurrentSourceConversionTable
, "Current Source"));
2886 Append(new SignedField
<5>(frsky
.varioCenterMax
));
2887 if (version
>= 216) {
2888 Append(new SignedField
<8>(frsky
.fasOffset
));
2894 RSSIConversionTable rssiConversionTable
[2];
2895 TelemetryVarioSourceConversionTable telemetryVarioSourceConversionTable
;
2896 ScreenTypesConversionTable screenTypesConversionTable
;
2897 TelemetryVoltsSourceConversionTable telemetryVoltsSourceConversionTable
;
2898 TelemetryCurrentSourceConversionTable telemetryCurrentSourceConversionTable
;
2901 class MavlinkField
: public StructField
{
2903 MavlinkField(MavlinkData
& mavlink
, BoardEnum board
, unsigned int version
):
2904 StructField("MavLink")
2906 Append(new UnsignedField
<4>(mavlink
.rc_rssi_scale
, "Rc_rssi_scale"));
2907 Append(new UnsignedField
<1>(mavlink
.pc_rssi_en
, "Pc_rssi_en"));
2908 Append(new SpareBitsField
<3>());
2909 Append(new SpareBitsField
<8>());
2910 Append(new SpareBitsField
<8>());
2911 Append(new SpareBitsField
<8>());
2919 class CustomScreenField
: public StructField
{
2921 CustomScreenField(CustomScreenData
& customScreen
):
2922 StructField("Custom Screen"),
2923 customScreen(customScreen
)
2928 CustomScreenData
& customScreen
;
2932 class SensorField
: public TransformedField
{
2934 SensorField(SensorData
& sensor
, BoardEnum board
, unsigned int version
):
2935 TransformedField(internalField
),
2936 internalField("Sensor"),
2941 internalField
.Append(new UnsignedField
<16>(_id
, "id/persistentValue"));
2942 internalField
.Append(new UnsignedField
<8>(_instance
, "instance/formula"));
2943 internalField
.Append(new ZCharField
<4>(sensor
.label
));
2944 internalField
.Append(new UnsignedField
<1>(sensor
.type
, "type"));
2945 internalField
.Append(new UnsignedField
<5>(sensor
.unit
, "unit"));
2946 internalField
.Append(new UnsignedField
<2>(sensor
.prec
, "prec"));
2947 internalField
.Append(new BoolField
<1>(sensor
.autoOffset
));
2948 internalField
.Append(new BoolField
<1>(sensor
.filter
));
2949 internalField
.Append(new BoolField
<1>(sensor
.logs
));
2950 internalField
.Append(new BoolField
<1>(sensor
.persistent
));
2951 internalField
.Append(new BoolField
<1>(sensor
.onlyPositive
));
2952 internalField
.Append(new UnsignedField
<3>(_subid
, "subid"));
2953 internalField
.Append(new UnsignedField
<32>(_param
, "param"));
2956 virtual void beforeExport()
2958 if (sensor
.type
== SensorData::TELEM_TYPE_CUSTOM
) {
2960 _subid
= sensor
.subid
;
2961 _instance
= sensor
.instance
;
2962 _ratio
= sensor
.ratio
;
2963 _offset
= sensor
.offset
;
2966 _id
= sensor
.persistentValue
;
2967 _instance
= sensor
.formula
;
2968 if (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
)
2969 _param
= (sensor
.source
) + (sensor
.index
<< 8);
2970 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
)
2971 _param
= ((uint8_t)sensor
.sources
[0]) + ((uint8_t)sensor
.sources
[1] << 8) + ((uint8_t)sensor
.sources
[2] << 16) + ((uint8_t)sensor
.sources
[3] << 24);
2972 else if (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
)
2973 _param
= (sensor
.gps
) + (sensor
.alt
<< 8);
2974 else if (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
|| sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
)
2975 _param
= (sensor
.amps
);
2979 virtual void afterImport()
2981 if (sensor
.type
== SensorData::TELEM_TYPE_CUSTOM
) {
2983 sensor
.subid
= _subid
;
2984 sensor
.instance
= _instance
;
2985 sensor
.ratio
= _ratio
;
2986 sensor
.offset
= _offset
;
2989 sensor
.persistentValue
= _id
;
2990 sensor
.formula
= _instance
;
2991 if (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
)
2992 (sensor
.source
= _sources
[0], sensor
.index
= _sources
[1]);
2993 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
)
2994 for (int i
=0; i
<4; ++i
)
2995 sensor
.sources
[i
] = _sources
[i
];
2996 else if (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
)
2997 (sensor
.gps
= _sources
[0], sensor
.alt
= _sources
[1]);
2998 else if (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
|| sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
)
2999 sensor
.amps
= _sources
[0];
3002 if (version
< 218) {
3003 if (sensor
.unit
> SensorData::UNIT_WATTS
)
3005 if (sensor
.unit
> SensorData::UNIT_DEGREE
)
3009 eepromImportDebug() << QString("imported %1").arg(internalField
.getName());
3013 StructField internalField
;
3014 SensorData
& sensor
;
3015 unsigned int version
;
3017 unsigned int _subid
;
3018 unsigned int _instance
;
3020 unsigned int _param
;
3021 uint8_t _sources
[4];
3029 int exportPpmDelay(int delay
) { return (delay
- 300) / 50; }
3030 int importPpmDelay(int delay
) { return 300 + 50 * delay
; }
3032 OpenTxModelData::OpenTxModelData(ModelData
& modelData
, BoardEnum board
, unsigned int version
, unsigned int variant
):
3033 TransformedField(internalField
),
3034 internalField("ModelData"),
3035 modelData(modelData
),
3039 protocolsConversionTable(board
)
3041 sprintf(name
, "Model %s", modelData
.name
);
3043 eepromImportDebug() << QString("OpenTxModelData::OpenTxModelData(name: %1, board: %2, ver: %3, var: %4)").arg(name
).arg(board
).arg(version
).arg(variant
);
3045 if (board
== BOARD_HORUS
)
3046 internalField
.Append(new ZCharField
<15>(modelData
.name
, "Model name"));
3047 else if (HAS_LARGE_LCD(board
))
3048 internalField
.Append(new ZCharField
<12>(modelData
.name
, "Model name"));
3050 internalField
.Append(new ZCharField
<10>(modelData
.name
, "Model name"));
3052 bool afterrelease21March2013
= IS_AFTER_RELEASE_21_MARCH_2013(board
, version
);
3054 if (afterrelease21March2013
) {
3055 internalField
.Append(new UnsignedField
<8>(modelData
.moduleData
[0].modelId
));
3057 if (IS_ARM(board
) && version
>= 217) {
3058 internalField
.Append(new UnsignedField
<8>(modelData
.moduleData
[1].modelId
));
3061 if (HAS_LARGE_LCD(board
) && version
>= 215) {
3062 internalField
.Append(new CharField
<10>(modelData
.bitmap
, true, "Model bitmap"));
3065 for (int i
=0; i
<MAX_TIMERS(board
, version
); i
++) {
3066 if (IS_ARM(board
) && version
>= 218) {
3067 internalField
.Append(new SwitchField
<9>(modelData
.timers
[i
].mode
, board
, version
, true));
3068 internalField
.Append(new UnsignedField
<23>(modelData
.timers
[i
].val
));
3069 internalField
.Append(new SignedField
<24>(modelData
.timers
[i
].pvalue
));
3070 internalField
.Append(new UnsignedField
<2>(modelData
.timers
[i
].countdownBeep
));
3071 internalField
.Append(new BoolField
<1>(modelData
.timers
[i
].minuteBeep
));
3072 internalField
.Append(new UnsignedField
<2>(modelData
.timers
[i
].persistent
));
3073 internalField
.Append(new SpareBitsField
<3>());
3074 if (HAS_LARGE_LCD(board
))
3075 internalField
.Append(new ZCharField
<8>(modelData
.timers
[i
].name
, "Timer name"));
3077 internalField
.Append(new ZCharField
<3>(modelData
.timers
[i
].name
, "Timer name"));
3079 else if (IS_ARM(board
) && version
>= 217) {
3080 internalField
.Append(new SwitchField
<8>(modelData
.timers
[i
].mode
, board
, version
, true));
3081 internalField
.Append(new UnsignedField
<24>(modelData
.timers
[i
].val
));
3082 internalField
.Append(new SignedField
<24>(modelData
.timers
[i
].pvalue
));
3083 internalField
.Append(new UnsignedField
<2>(modelData
.timers
[i
].countdownBeep
));
3084 internalField
.Append(new BoolField
<1>(modelData
.timers
[i
].minuteBeep
));
3085 internalField
.Append(new UnsignedField
<2>(modelData
.timers
[i
].persistent
));
3086 internalField
.Append(new SpareBitsField
<3>());
3087 if (IS_TARANIS(board
))
3088 internalField
.Append(new ZCharField
<8>(modelData
.timers
[i
].name
, "Timer name"));
3090 internalField
.Append(new ZCharField
<3>(modelData
.timers
[i
].name
, "Timer name"));
3092 else if ((IS_ARM(board
) || IS_2560(board
)) && version
>= 216) {
3093 internalField
.Append(new SwitchField
<8>(modelData
.timers
[i
].mode
, board
, version
, true));
3094 internalField
.Append(new UnsignedField
<16>(modelData
.timers
[i
].val
));
3095 internalField
.Append(new UnsignedField
<2>(modelData
.timers
[i
].countdownBeep
));
3096 internalField
.Append(new BoolField
<1>(modelData
.timers
[i
].minuteBeep
));
3097 internalField
.Append(new UnsignedField
<2>(modelData
.timers
[i
].persistent
));
3098 internalField
.Append(new SpareBitsField
<3>());
3099 internalField
.Append(new SignedField
<16>(modelData
.timers
[i
].pvalue
));
3101 else if (afterrelease21March2013
) {
3102 internalField
.Append(new SwitchField
<8>(modelData
.timers
[i
].mode
, board
, version
, true));
3103 internalField
.Append(new UnsignedField
<12>(modelData
.timers
[i
].val
));
3104 internalField
.Append(new BoolField
<1>((bool &)modelData
.timers
[i
].countdownBeep
));
3105 internalField
.Append(new BoolField
<1>(modelData
.timers
[i
].minuteBeep
));
3106 if (HAS_PERSISTENT_TIMERS(board
)) {
3107 internalField
.Append(new UnsignedField
<1>(modelData
.timers
[i
].persistent
));
3108 internalField
.Append(new SpareBitsField
<1>());
3109 internalField
.Append(new SignedField
<16>(modelData
.timers
[i
].pvalue
));
3112 internalField
.Append(new SpareBitsField
<2>());
3116 internalField
.Append(new SwitchField
<8>(modelData
.timers
[i
].mode
, board
, version
, true));
3117 internalField
.Append(new UnsignedField
<16>(modelData
.timers
[i
].val
));
3118 if (HAS_PERSISTENT_TIMERS(board
)) {
3119 internalField
.Append(new UnsignedField
<1>(modelData
.timers
[i
].persistent
));
3120 internalField
.Append(new SpareBitsField
<15>());
3126 internalField
.Append(new UnsignedField
<3>(modelData
.telemetryProtocol
));
3128 internalField
.Append(new ConversionField
< UnsignedField
<3> >((unsigned int &)modelData
.moduleData
[0].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this telemetry protocol")));
3130 internalField
.Append(new BoolField
<1>(modelData
.thrTrim
));
3132 if (IS_ARM(board
) && version
>= 217) {
3133 internalField
.Append(new BoolField
<1>(modelData
.noGlobalFunctions
));
3134 internalField
.Append(new UnsignedField
<2>(modelData
.trimsDisplay
));
3135 internalField
.Append(new BoolField
<1>(modelData
.frsky
.ignoreSensorIds
));
3137 else if (IS_TARANIS(board
) || (IS_ARM(board
) && version
>= 216)) {
3138 internalField
.Append(new SpareBitsField
<4>());
3141 internalField
.Append(new ConversionField
< SignedField
<4> >(modelData
.moduleData
[0].channelsCount
, &channelsConversionTable
, "Channels number", ::QObject::tr("OpenTX doesn't allow this number of channels")));
3145 internalField
.Append(new SignedField
<3>(modelData
.trimInc
));
3147 internalField
.Append(new ConversionField
< SignedField
<3> >(modelData
.trimInc
, +2));
3149 internalField
.Append(new BoolField
<1>(modelData
.disableThrottleWarning
));
3151 if (IS_TARANIS(board
) || (IS_ARM(board
) && version
>= 216))
3152 internalField
.Append(new BoolField
<1>(modelData
.displayChecklist
));
3154 internalField
.Append(new BoolField
<1>(modelData
.moduleData
[0].ppm
.pulsePol
));
3156 internalField
.Append(new BoolField
<1>(modelData
.extendedLimits
));
3157 internalField
.Append(new BoolField
<1>(modelData
.extendedTrims
));
3158 internalField
.Append(new BoolField
<1>(modelData
.throttleReversed
));
3160 if (!IS_ARM(board
) || version
< 216) {
3161 internalField
.Append(new ConversionField
< SignedField
<8> >(modelData
.moduleData
[0].ppm
.delay
, exportPpmDelay
, importPpmDelay
));
3164 if (IS_ARM(board
) || IS_2560(board
))
3165 internalField
.Append(new UnsignedField
<16>(modelData
.beepANACenter
));
3167 internalField
.Append(new UnsignedField
<8>(modelData
.beepANACenter
));
3169 for (int i
=0; i
<MAX_MIXERS(board
, version
); i
++)
3170 internalField
.Append(new MixField(modelData
.mixData
[i
], board
, version
, &modelData
));
3171 for (int i
=0; i
<MAX_CHANNELS(board
, version
); i
++)
3172 internalField
.Append(new LimitField(modelData
.limitData
[i
], board
, version
));
3173 for (int i
=0; i
<MAX_EXPOS(board
, version
); i
++)
3174 internalField
.Append(new InputField(modelData
.expoData
[i
], board
, version
));
3175 internalField
.Append(new CurvesField(modelData
.curves
, board
, version
));
3176 for (int i
=0; i
<MAX_LOGICAL_SWITCHES(board
, version
); i
++)
3177 internalField
.Append(new LogicalSwitchField(modelData
.logicalSw
[i
], board
, version
, variant
, &modelData
));
3178 for (int i
=0; i
<MAX_CUSTOM_FUNCTIONS(board
, version
); i
++) {
3180 internalField
.Append(new ArmCustomFunctionField(modelData
.customFn
[i
], board
, version
, variant
));
3182 internalField
.Append(new AvrCustomFunctionField(modelData
.customFn
[i
], board
, version
, variant
));
3184 internalField
.Append(new HeliField(modelData
.swashRingData
, board
, version
, variant
));
3185 for (int i
=0; i
<MAX_FLIGHT_MODES(board
, version
); i
++) {
3186 internalField
.Append(new FlightModeField(modelData
.flightModeData
[i
], i
, board
, version
));
3189 if (!IS_ARM(board
) || version
< 216) {
3190 internalField
.Append(new SignedField
<8>(modelData
.moduleData
[0].ppm
.frameLength
));
3193 internalField
.Append(new UnsignedField
<8>(modelData
.thrTraceSrc
, "Throttle Source"));
3195 if (!afterrelease21March2013
) {
3196 internalField
.Append(new UnsignedField
<8>(modelData
.moduleData
[0].modelId
));
3199 if (IS_HORUS(board
))
3200 internalField
.Append(new SwitchesWarningField
<32>(modelData
.switchWarningStates
, board
, version
));
3201 else if (IS_TARANIS_X9E(board
))
3202 internalField
.Append(new SwitchesWarningField
<64>(modelData
.switchWarningStates
, board
, version
));
3203 else if (IS_TARANIS(board
))
3204 internalField
.Append(new SwitchesWarningField
<16>(modelData
.switchWarningStates
, board
, version
));
3206 internalField
.Append(new SwitchesWarningField
<8>(modelData
.switchWarningStates
, board
, version
));
3209 if (IS_TARANIS_X9E(board
))
3210 internalField
.Append(new UnsignedField
<32>(modelData
.switchWarningEnable
));
3211 else if (!IS_HORUS(board
) && version
>= 216)
3212 internalField
.Append(new UnsignedField
<8>(modelData
.switchWarningEnable
));
3214 if (board
!= BOARD_STOCK
&& (board
!= BOARD_M128
|| version
< 215)) {
3215 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
3216 if (version
>= 218) {
3217 internalField
.Append(new ZCharField
<3>(modelData
.gvars_names
[i
], "GVar name"));
3218 internalField
.Append(new SpareBitsField
<12>()); // TODO min
3219 internalField
.Append(new SpareBitsField
<12>()); // TODO max
3220 internalField
.Append(new BoolField
<1>(modelData
.gvars_popups
[i
]));
3221 internalField
.Append(new SpareBitsField
<1>());
3222 internalField
.Append(new SpareBitsField
<2>());
3223 internalField
.Append(new SpareBitsField
<4>());
3226 internalField
.Append(new ZCharField
<6>(modelData
.gvars_names
[i
], "GVar name"));
3227 if (version
>= 216) {
3228 internalField
.Append(new BoolField
<1>(modelData
.gvars_popups
[i
]));
3229 internalField
.Append(new SpareBitsField
<7>());
3234 else if (variant
& GVARS_VARIANT
) {
3235 for (int i
=0; i
<MAX_GVARS(board
, version
); i
++) {
3236 // on M64 GVARS are common to all flight modes, and there is no name
3237 internalField
.Append(new SignedField
<16>(modelData
.flightModeData
[0].gvars
[i
]));
3241 if ((board
!= BOARD_STOCK
&& (board
!= BOARD_M128
|| version
< 215)) || (variant
& FRSKY_VARIANT
)) {
3242 internalField
.Append(new FrskyField(modelData
.frsky
, board
, version
, variant
));
3244 else if ((board
== BOARD_STOCK
|| board
== BOARD_M128
) && (variant
& MAVLINK_VARIANT
)) {
3245 internalField
.Append(new MavlinkField(modelData
.mavlink
, board
, version
));
3248 if (IS_TARANIS(board
) && version
< 215) {
3249 internalField
.Append(new CharField
<10>(modelData
.bitmap
, true, "Model bitmap"));
3252 int modulesCount
= 2;
3254 if (IS_STM32(board
)) {
3256 if (version
>= 217) {
3257 internalField
.Append(new SpareBitsField
<3>());
3258 internalField
.Append(new UnsignedField
<3>(modelData
.trainerMode
));
3259 internalField
.Append(new UnsignedField
<2>(modelData
.potsWarningMode
));
3262 internalField
.Append(new ConversionField
< SignedField
<8> >(modelData
.moduleData
[1].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
3263 internalField
.Append(new UnsignedField
<8>(modelData
.trainerMode
));
3266 else if (IS_ARM(board
)) {
3267 if (version
>= 217) {
3269 internalField
.Append(new SpareBitsField
<6>());
3270 internalField
.Append(new UnsignedField
<2>(modelData
.potsWarningMode
));
3272 else if (version
>= 216) {
3274 internalField
.Append(new ConversionField
< SignedField
<8> >(modelData
.moduleData
[0].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
3278 if (IS_ARM(board
) && version
>= 215) {
3279 for (int module
=0; module
<modulesCount
; module
++) {
3280 if (version
>= 217) {
3281 internalField
.Append(new ConversionField
<SignedField
<4> >(modelData
.moduleData
[module
].protocol
, &protocolsConversionTable
, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
3282 internalField
.Append(new SignedField
<4>(subprotocols
[module
]));
3285 internalField
.Append(new SignedField
<8>(subprotocols
[module
]));
3287 internalField
.Append(new UnsignedField
<8>(modelData
.moduleData
[module
].channelsStart
));
3288 internalField
.Append(new ConversionField
<SignedField
<8> >(modelData
.moduleData
[module
].channelsCount
, -8));
3289 if (version
>= 217) {
3290 internalField
.Append(new UnsignedField
<4>(modelData
.moduleData
[module
].failsafeMode
));
3291 internalField
.Append(new UnsignedField
<3>(modelData
.moduleData
[module
].subType
));
3292 internalField
.Append(new BoolField
<1>(modelData
.moduleData
[module
].invertedSerial
));
3295 internalField
.Append(new ConversionField
<UnsignedField
<8> >(modelData
.moduleData
[module
].failsafeMode
, -1));
3297 for (int i
=0; i
<32; i
++) {
3298 internalField
.Append(new SignedField
<16>(modelData
.moduleData
[module
].failsafeChannels
[i
]));
3300 if (version
>= 217) {
3301 internalField
.Append(new ConversionField
< SignedField
<6> >(modelData
.moduleData
[module
].ppm
.delay
, exportPpmDelay
, importPpmDelay
));
3302 internalField
.Append(new BoolField
<1>(modelData
.moduleData
[module
].ppm
.pulsePol
));
3303 internalField
.Append(new BoolField
<1>(modelData
.moduleData
[module
].ppm
.outputType
));
3304 internalField
.Append(new SignedField
<8>(modelData
.moduleData
[module
].ppm
.frameLength
));
3307 internalField
.Append(new ConversionField
< SignedField
<8> >(modelData
.moduleData
[module
].ppm
.delay
, exportPpmDelay
, importPpmDelay
));
3308 internalField
.Append(new SignedField
<8>(modelData
.moduleData
[module
].ppm
.frameLength
));
3309 internalField
.Append(new BoolField
<8>(modelData
.moduleData
[module
].ppm
.pulsePol
));
3314 if (IS_TARANIS(board
) && version
< 218) {
3315 for (int i
=0; i
<MAX_CURVES(board
, version
); i
++) {
3316 internalField
.Append(new ZCharField
<6>(modelData
.curves
[i
].name
, "Curve name"));
3320 if (IS_STM32(board
)) {
3321 if (version
>= 218) {
3322 for (int i
=0; i
<MAX_SCRIPTS(board
); i
++) {
3323 ScriptData
& script
= modelData
.scriptData
[i
];
3324 internalField
.Append(new CharField
<6>(script
.filename
, true, "Script filename"));
3325 internalField
.Append(new ZCharField
<6>(script
.name
, "Script name"));
3326 for (int j
=0; j
<6; j
++) {
3327 internalField
.Append(new SignedField
<16>(script
.inputs
[j
]));
3331 else if (version
>= 217) {
3332 for (int i
=0; i
<7; i
++) {
3333 ScriptData
& script
= modelData
.scriptData
[i
];
3334 internalField
.Append(new CharField
<8>(script
.filename
, true, "Script filename"));
3335 internalField
.Append(new ZCharField
<8>(script
.name
, "Script name"));
3336 for (int j
=0; j
<8; j
++) {
3337 internalField
.Append(new SignedField
<8>(script
.inputs
[j
]));
3341 else if (version
>= 216) {
3342 for (int i
=0; i
<7; i
++) {
3343 ScriptData
& script
= modelData
.scriptData
[i
];
3344 internalField
.Append(new CharField
<10>(script
.filename
, true, "Script filename"));
3345 internalField
.Append(new ZCharField
<10>(script
.name
, "Script name"));
3346 for (int j
=0; j
<10; j
++) {
3347 internalField
.Append(new SignedField
<8>(script
.inputs
[j
]));
3353 if (IS_ARM(board
) && version
>= 216) {
3354 for (int i
=0; i
<32; i
++) {
3355 if (HAS_LARGE_LCD(board
))
3356 internalField
.Append(new ZCharField
<4>(modelData
.inputNames
[i
], "Input name"));
3358 internalField
.Append(new ZCharField
<3>(modelData
.inputNames
[i
], "Input name"));
3362 if (IS_ARM(board
) && version
>= 217) {
3363 for (int i
=0; i
<8; i
++) {
3364 if (i
< MAX_POTS(board
, version
)+MAX_SLIDERS(board
))
3365 internalField
.Append(new BoolField
<1>(modelData
.potsWarningEnabled
[i
]));
3367 internalField
.Append(new SpareBitsField
<1>());
3370 else if (IS_ARM(board
) && version
>= 216) {
3371 for (int i
=0; i
<6; i
++) {
3372 if (i
< MAX_POTS(board
, version
)+MAX_SLIDERS(board
))
3373 internalField
.Append(new BoolField
<1>(modelData
.potsWarningEnabled
[i
]));
3375 internalField
.Append(new SpareBitsField
<1>());
3377 internalField
.Append(new UnsignedField
<2>(modelData
.potsWarningMode
));
3380 if (IS_ARM(board
) && version
>= 216) {
3381 for (int i
=0; i
< MAX_POTS(board
, version
)+MAX_SLIDERS(board
); i
++) {
3382 internalField
.Append(new SignedField
<8>(modelData
.potPosition
[i
]));
3386 if (IS_ARM(board
) && version
== 216) {
3387 internalField
.Append(new SpareBitsField
<16>());
3390 if (IS_SKY9X(board
) && version
>= 217) {
3391 internalField
.Append(new SpareBitsField
<8>());
3392 internalField
.Append(new SpareBitsField
<8>());
3395 if (IS_ARM(board
) && version
>= 217) {
3396 for (int i
=0; i
<MAX_TELEMETRY_SENSORS(board
, version
); ++i
) {
3397 internalField
.Append(new SensorField(modelData
.sensorData
[i
], board
, version
));
3401 if (IS_TARANIS_X9E(board
)) {
3402 internalField
.Append(new UnsignedField
<8>(modelData
.toplcdTimer
));
3405 if (IS_HORUS(board
)) {
3406 for (int i
= 0; i
< 5; i
++) {
3407 internalField
.Append(new CharField
<610>(modelData
.customScreenData
[i
], false, "Custom screen blob"));
3409 internalField
.Append(new CharField
<216>(modelData
.topbarData
, false, "Top bar blob"));
3410 internalField
.Append(new SpareBitsField
<8>()); // current view
3414 void OpenTxModelData::beforeExport()
3416 // qDebug() << QString("before export model") << modelData.name;
3418 for (int module
=0; module
<3; module
++) {
3419 if (modelData
.moduleData
[module
].protocol
>= PULSES_PXX_XJT_X16
&& modelData
.moduleData
[module
].protocol
<= PULSES_PXX_XJT_LR12
) {
3420 subprotocols
[module
] = modelData
.moduleData
[module
].protocol
- PULSES_PXX_XJT_X16
;
3422 else if (modelData
.moduleData
[module
].protocol
>= PULSES_LP45
&& modelData
.moduleData
[module
].protocol
<= PULSES_DSMX
) {
3423 subprotocols
[module
] = modelData
.moduleData
[module
].protocol
- PULSES_LP45
;
3425 else if (modelData
.moduleData
[module
].protocol
== PULSES_MULTIMODULE
) {
3426 // copy multi settings to ppm settings to get them written to the eeprom
3427 // (reverse the int => ms logic of the ppm delay) since only ppm is written
3428 subprotocols
[module
] = modelData
.moduleData
[module
].multi
.rfProtocol
& (0x1f);
3429 int multiByte
= ((modelData
.moduleData
[module
].multi
.rfProtocol
>> 4) & 0x03) | (modelData
.moduleData
[module
].multi
.customProto
<< 7);
3430 modelData
.moduleData
[module
].ppm
.delay
= 300 + 50 * multiByte
;
3431 modelData
.moduleData
[module
].ppm
.frameLength
= modelData
.moduleData
[module
].multi
.optionValue
;
3432 modelData
.moduleData
[module
].ppm
.outputType
= modelData
.moduleData
[module
].multi
.lowPowerMode
;
3433 modelData
.moduleData
[module
].ppm
.pulsePol
= modelData
.moduleData
[module
].multi
.autoBindMode
;
3436 subprotocols
[module
] = (module
== 0 ? -1 : 0);
3440 if (IS_HORUS(board
)) {
3441 uint32_t newSwitchWarningStates
= 0;
3442 for (int i
= 0; i
< MAX_SWITCHES(board
, version
); i
++) {
3443 uint8_t value
= (modelData
.switchWarningStates
>> (2*i
)) & 0x03;
3444 if (!(modelData
.switchWarningEnable
& (1 << i
))) {
3445 newSwitchWarningStates
|= (value
+ 1) << (3*i
);
3448 modelData
.switchWarningStates
= newSwitchWarningStates
;
3452 void OpenTxModelData::afterImport()
3454 eepromImportDebug() << QString("OpenTxModelData::afterImport()") << modelData
.name
;
3456 if (IS_TARANIS(board
) && version
< 216) {
3457 for (unsigned int i
=0; i
<CPN_MAX_STICKS
; i
++) {
3458 for (int j
=0; j
<64; j
++) {
3459 ExpoData
* expo
= &modelData
.expoData
[j
];
3460 if (expo
->mode
== INPUT_MODE_BOTH
&& expo
->chn
== i
&& expo
->flightModes
== 0 && expo
->swtch
.type
== SWITCH_TYPE_NONE
)
3462 if (expo
->mode
== 0 || expo
->chn
> i
) {
3463 ExpoData
* newExpo
= modelData
.insertInput(j
);
3464 newExpo
->mode
= INPUT_MODE_BOTH
;
3465 newExpo
->srcRaw
= RawSource(SOURCE_TYPE_STICK
, i
);
3467 newExpo
->weight
= 100;
3471 strncpy(modelData
.inputNames
[i
], GetCurrentFirmware()->getAnalogInputName(i
).toLatin1().constData(), sizeof(modelData
.inputNames
[i
])-1);
3475 for (int module
=0; module
<3; module
++) {
3476 if (modelData
.moduleData
[module
].protocol
== PULSES_PXX_XJT_X16
|| modelData
.moduleData
[module
].protocol
== PULSES_LP45
) {
3477 if (subprotocols
[module
] >= 0)
3478 modelData
.moduleData
[module
].protocol
+= subprotocols
[module
];
3480 modelData
.moduleData
[module
].protocol
= PULSES_OFF
;
3482 else if (modelData
.moduleData
[module
].protocol
== PULSES_MULTIMODULE
) {
3483 // Copy data from ppm struct to multi struct
3484 unsigned int multiByte
= (unsigned int)((modelData
.moduleData
[module
].ppm
.delay
- 300) / 50);
3485 modelData
.moduleData
[module
].multi
.rfProtocol
= subprotocols
[module
] | ((multiByte
& 0x3) << 4);
3486 modelData
.moduleData
[module
].multi
.customProto
= (multiByte
& 0x80) == 0x80;
3487 modelData
.moduleData
[module
].multi
.optionValue
= modelData
.moduleData
[module
].ppm
.frameLength
;
3488 modelData
.moduleData
[module
].multi
.lowPowerMode
= modelData
.moduleData
[module
].ppm
.outputType
;
3489 modelData
.moduleData
[module
].multi
.autoBindMode
= modelData
.moduleData
[module
].ppm
.pulsePol
;
3493 if (IS_TARANIS(board
) && version
< 217 && modelData
.moduleData
[1].protocol
!= PULSES_OFF
) {
3494 modelData
.moduleData
[1].modelId
= modelData
.moduleData
[0].modelId
;
3497 if (IS_HORUS(board
)) {
3498 uint32_t newSwitchWarningStates
= 0;
3499 for (int i
= 0; i
< MAX_SWITCHES(board
, version
); i
++) {
3500 uint8_t value
= (modelData
.switchWarningStates
>> (3*i
)) & 0x07;
3502 modelData
.switchWarningEnable
|= (1 << i
);
3504 newSwitchWarningStates
|= ((value
& 0x03) - 1) << (2*i
);
3506 modelData
.switchWarningStates
= newSwitchWarningStates
;
3510 OpenTxGeneralData::OpenTxGeneralData(GeneralSettings
& generalData
, BoardEnum board
, unsigned int version
, unsigned int variant
):
3511 TransformedField(internalField
),
3512 internalField("General Settings"),
3513 generalData(generalData
),
3516 inputsCount(CPN_MAX_STICKS
+MAX_POTS(board
, version
)+MAX_SLIDERS(board
)+MAX_MOUSE_ANALOGS(board
))
3518 eepromImportDebug() << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board
).arg(version
).arg(variant
);
3520 generalData
.version
= version
;
3521 generalData
.variant
= variant
;
3523 internalField
.Append(new UnsignedField
<8>(generalData
.version
));
3524 if (version
>= 213 || (!IS_ARM(board
) && version
>= 212))
3525 internalField
.Append(new UnsignedField
<16>(generalData
.variant
));
3527 if (version
>= 216) {
3528 for (int i
=0; i
<inputsCount
; i
++) {
3529 internalField
.Append(new SignedField
<16>(generalData
.calibMid
[i
]));
3530 internalField
.Append(new SignedField
<16>(generalData
.calibSpanNeg
[i
]));
3531 internalField
.Append(new SignedField
<16>(generalData
.calibSpanPos
[i
]));
3535 for (int i
=0; i
<inputsCount
; i
++) {
3536 if (!IS_TARANIS(board
) || i
!=6)
3537 internalField
.Append(new SignedField
<16>(generalData
.calibMid
[i
]));
3539 for (int i
=0; i
<inputsCount
; i
++) {
3540 if (!IS_TARANIS(board
) || i
!=6)
3541 internalField
.Append(new SignedField
<16>(generalData
.calibSpanNeg
[i
]));
3543 for (int i
=0; i
<inputsCount
; i
++) {
3544 if (!IS_TARANIS(board
) || i
!=6)
3545 internalField
.Append(new SignedField
<16>(generalData
.calibSpanPos
[i
]));
3549 internalField
.Append(new UnsignedField
<16>(chkSum
));
3550 if (!IS_HORUS(board
)) {
3551 internalField
.Append(new UnsignedField
<8>(generalData
.currModelIndex
));
3552 internalField
.Append(new UnsignedField
<8>(generalData
.contrast
));
3554 internalField
.Append(new UnsignedField
<8>(generalData
.vBatWarn
));
3555 internalField
.Append(new SignedField
<8>(generalData
.txVoltageCalibration
));
3556 internalField
.Append(new SignedField
<8>(generalData
.backlightMode
));
3558 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
3559 internalField
.Append(new SignedField
<16>(generalData
.trainer
.calib
[i
]));
3561 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
3562 internalField
.Append(new UnsignedField
<6>(generalData
.trainer
.mix
[i
].src
));
3563 internalField
.Append(new UnsignedField
<2>(generalData
.trainer
.mix
[i
].mode
));
3564 internalField
.Append(new SignedField
<8>(generalData
.trainer
.mix
[i
].weight
));
3567 internalField
.Append(new UnsignedField
<8>(generalData
.view
, 0, MAX_VIEWS(board
)-1));
3569 internalField
.Append(new SpareBitsField
<2>()); // TODO buzzerMode?
3570 internalField
.Append(new BoolField
<1>(generalData
.fai
));
3571 internalField
.Append(new SignedField
<2>((int &)generalData
.beeperMode
));
3572 internalField
.Append(new BoolField
<1>(generalData
.flashBeep
));
3573 internalField
.Append(new BoolField
<1>(generalData
.disableMemoryWarning
));
3574 internalField
.Append(new BoolField
<1>(generalData
.disableAlarmWarning
));
3576 internalField
.Append(new UnsignedField
<2>(generalData
.stickMode
));
3577 internalField
.Append(new SignedField
<5>(generalData
.timezone
));
3578 if (version
>= 217 && IS_TARANIS(board
)) {
3579 internalField
.Append(new BoolField
<1>(generalData
.adjustRTC
));
3582 internalField
.Append(new SpareBitsField
<1>());
3585 internalField
.Append(new UnsignedField
<8>(generalData
.inactivityTimer
));
3587 if (version
>= 215) {
3588 internalField
.Append(new UnsignedField
<3>(generalData
.mavbaud
));
3591 internalField
.Append(new SpareBitsField
<1>());
3592 internalField
.Append(new BoolField
<1>(generalData
.minuteBeep
));
3593 internalField
.Append(new BoolField
<1>(generalData
.preBeep
));
3597 internalField
.Append(new SpareBitsField
<3>());
3599 if (version
>= 216 && IS_TARANIS(board
))
3600 internalField
.Append(new SignedField
<3>(generalData
.splashDuration
));
3601 else if (version
>= 213 || (!IS_ARM(board
) && version
>= 212))
3602 internalField
.Append(new UnsignedField
<3>(generalData
.splashMode
)); // TODO
3604 internalField
.Append(new SpareBitsField
<3>());
3605 internalField
.Append(new SignedField
<2>((int &)generalData
.hapticMode
));
3608 internalField
.Append(new SignedField
<8>(generalData
.switchesDelay
));
3610 internalField
.Append(new SpareBitsField
<8>()); // TODO blOffBright + blOnBright
3612 internalField
.Append(new UnsignedField
<8>(generalData
.backlightDelay
));
3613 internalField
.Append(new UnsignedField
<8>(generalData
.templateSetup
));
3614 internalField
.Append(new SignedField
<8>(generalData
.PPM_Multiplier
));
3615 internalField
.Append(new SignedField
<8>(generalData
.hapticLength
));
3617 if (version
< 216 || (version
< 218 && !IS_9X(board
)) || (!IS_9X(board
) && !IS_TARANIS(board
) && !IS_HORUS(board
))) {
3618 internalField
.Append(new UnsignedField
<8>(generalData
.reNavigation
));
3621 if (version
>= 216 && !IS_TARANIS(board
) && !IS_HORUS(board
)) {
3622 internalField
.Append(new UnsignedField
<8>(generalData
.stickReverse
));
3625 internalField
.Append(new SignedField
<3>(generalData
.beeperLength
));
3626 internalField
.Append(new SignedField
<3>(generalData
.hapticStrength
));
3627 internalField
.Append(new UnsignedField
<1>(generalData
.gpsFormat
));
3628 internalField
.Append(new SpareBitsField
<1>()); // unexpectedShutdown
3630 internalField
.Append(new UnsignedField
<8>(generalData
.speakerPitch
));
3633 internalField
.Append(new ConversionField
< SignedField
<8> >(generalData
.speakerVolume
, -12, 0, 0, 23, "Volume"));
3635 internalField
.Append(new ConversionField
< SignedField
<8> >(generalData
.speakerVolume
, -7, 0, 0, 7, "Volume"));
3637 if (version
>= 214 || (!IS_ARM(board
) && version
>= 213)) {
3638 internalField
.Append(new SignedField
<8>(generalData
.vBatMin
));
3639 internalField
.Append(new SignedField
<8>(generalData
.vBatMax
));
3642 if (IS_ARM(board
)) {
3643 internalField
.Append(new UnsignedField
<8>(generalData
.backlightBright
));
3644 if (version
< 218) internalField
.Append(new SignedField
<8>(generalData
.txCurrentCalibration
));
3645 if (version
>= 213) {
3646 if (version
< 218) internalField
.Append(new SignedField
<8>(generalData
.temperatureWarn
)); // TODO
3647 if (version
< 218) internalField
.Append(new UnsignedField
<8>(generalData
.mAhWarn
));
3648 if (version
< 218) internalField
.Append(new UnsignedField
<16>(generalData
.mAhUsed
));
3649 internalField
.Append(new UnsignedField
<32>(generalData
.globalTimer
));
3650 if (version
< 218) internalField
.Append(new SignedField
<8>(generalData
.temperatureCalib
)); // TODO
3651 internalField
.Append(new UnsignedField
<8>(generalData
.btBaudrate
)); // TODO
3652 if (version
< 218) internalField
.Append(new BoolField
<8>(generalData
.optrexDisplay
)); //TODO
3653 if (version
< 218) internalField
.Append(new UnsignedField
<8>(generalData
.sticksGain
)); // TODO
3655 if (version
>= 214) {
3656 if (version
< 218) internalField
.Append(new UnsignedField
<8>(generalData
.rotarySteps
)); // TODO
3657 internalField
.Append(new UnsignedField
<8>(generalData
.countryCode
));
3658 internalField
.Append(new UnsignedField
<1>(generalData
.imperial
));
3659 if (version
>= 218) {
3660 internalField
.Append(new BoolField
<1>(generalData
.jitterFilter
));
3661 internalField
.Append(new SpareBitsField
<6>());
3664 internalField
.Append(new SpareBitsField
<7>());
3667 if (version
>= 215) {
3668 internalField
.Append(new CharField
<2>(generalData
.ttsLanguage
, true, "TTS language"));
3669 if (version
>= 218) {
3670 internalField
.Append(new SignedField
<4>(generalData
.beepVolume
));
3671 internalField
.Append(new SignedField
<4>(generalData
.wavVolume
));
3672 internalField
.Append(new SignedField
<4>(generalData
.varioVolume
));
3673 internalField
.Append(new SignedField
<4>(generalData
.backgroundVolume
));
3676 internalField
.Append(new SignedField
<8>(generalData
.beepVolume
));
3677 internalField
.Append(new SignedField
<8>(generalData
.wavVolume
));
3678 internalField
.Append(new SignedField
<8>(generalData
.varioVolume
));
3680 if (version
>= 216) {
3681 internalField
.Append(new SignedField
<8>(generalData
.varioPitch
));
3682 internalField
.Append(new SignedField
<8>(generalData
.varioRange
));
3683 internalField
.Append(new SignedField
<8>(generalData
.varioRepeat
));
3685 if (version
< 218) internalField
.Append(new SignedField
<8>(generalData
.backgroundVolume
));
3687 if (version
>= 218) {
3688 for (int i
=0; i
<MAX_CUSTOM_FUNCTIONS(board
, version
); i
++) {
3689 internalField
.Append(new ArmCustomFunctionField(generalData
.customFn
[i
], board
, version
, variant
));
3693 if (IS_STM32(board
) && version
>= 216) {
3694 if (version
>= 218) {
3695 internalField
.Append(new UnsignedField
<4>(generalData
.hw_uartMode
));
3696 for (uint8_t i
=0; i
<4; i
++) {
3697 internalField
.Append(new UnsignedField
<1>(generalData
.sliderConfig
[i
]));
3700 else if (version
>= 217) {
3701 internalField
.Append(new UnsignedField
<6>(generalData
.hw_uartMode
));
3702 if (IS_TARANIS_X9E(board
)) {
3703 internalField
.Append(new UnsignedField
<1>(generalData
.sliderConfig
[2]));
3704 internalField
.Append(new UnsignedField
<1>(generalData
.sliderConfig
[3]));
3707 internalField
.Append(new SpareBitsField
<2>());
3711 internalField
.Append(new UnsignedField
<8>(generalData
.hw_uartMode
));
3713 if (IS_HORUS(board
)) {
3714 for (int i
=0; i
<16; i
++) {
3715 if (i
< MAX_SWITCHES(board
, version
))
3716 internalField
.Append(new UnsignedField
<2>(generalData
.switchConfig
[i
]));
3718 internalField
.Append(new SpareBitsField
<2>());
3721 for (int i
=0; i
<4; i
++) {
3722 if (i
< MAX_POTS(board
, version
))
3723 internalField
.Append(new UnsignedField
<2>(generalData
.potConfig
[i
]));
3725 internalField
.Append(new SpareBitsField
<2>());
3727 if (!IS_HORUS(board
))
3728 internalField
.Append(new UnsignedField
<8>(generalData
.backlightColor
));
3731 if (IS_TARANIS_X9E(board
))
3732 internalField
.Append(new SpareBitsField
<64>()); // switchUnlockStates
3733 else if (IS_TARANIS(board
))
3734 internalField
.Append(new SpareBitsField
<16>()); // switchUnlockStates
3736 if (version
== 217) {
3737 for (int i
=0; i
<MAX_CUSTOM_FUNCTIONS(board
, version
); i
++) {
3738 internalField
.Append(new ArmCustomFunctionField(generalData
.customFn
[i
], board
, version
, variant
));
3742 if (IS_HORUS(board
)) {
3743 for (int i
=0; i
<MAX_SWITCHES(board
, version
); ++i
) {
3744 internalField
.Append(new ZCharField
<3>(generalData
.switchName
[i
], "Switch name"));
3746 for (int i
=0; i
<CPN_MAX_STICKS
; ++i
) {
3747 internalField
.Append(new ZCharField
<3>(generalData
.stickName
[i
], "Stick name"));
3749 for (int i
=0; i
<MAX_POTS(board
, version
); ++i
) {
3750 internalField
.Append(new ZCharField
<3>(generalData
.potName
[i
], "Pot name"));
3752 for (int i
=0; i
<MAX_SLIDERS(board
); ++i
) {
3753 internalField
.Append(new ZCharField
<3>(generalData
.sliderName
[i
], "Slider name"));
3755 internalField
.Append(new CharField
<17>(generalData
.currModelFilename
, true, "Current model filename"));
3757 else if (IS_TARANIS(board
) && version
>= 217) {
3758 for (int i
=0; i
<MAX_SWITCHES(board
, version
); i
++) {
3759 internalField
.Append(new UnsignedField
<2>(generalData
.switchConfig
[i
]));
3761 if (IS_TARANIS_X9E(board
)) {
3762 internalField
.Append(new SpareBitsField
<64-2*18>());
3764 for (int i
=0; i
<MAX_SWITCHES(board
, version
); ++i
) {
3765 internalField
.Append(new ZCharField
<3>(generalData
.switchName
[i
], "Switch name"));
3767 for (int i
=0; i
<CPN_MAX_STICKS
; ++i
) {
3768 internalField
.Append(new ZCharField
<3>(generalData
.stickName
[i
], "Stick name"));
3770 for (int i
=0; i
<MAX_POTS(board
, version
); ++i
) {
3771 internalField
.Append(new ZCharField
<3>(generalData
.potName
[i
], "Pot name"));
3773 for (int i
=0; i
<MAX_SLIDERS(board
); ++i
) {
3774 internalField
.Append(new ZCharField
<3>(generalData
.sliderName
[i
], "Slider name"));
3778 if (IS_HORUS(board
)) {
3779 internalField
.Append(new BoolField
<1>(generalData
.bluetoothEnable
));
3780 internalField
.Append(new UnsignedField
<7>(generalData
.backlightOffBright
));
3781 internalField
.Append(new ZCharField
<10>(generalData
.bluetoothName
, "Bluetooth name"));
3783 else if (IS_TARANIS_X9E(board
) && version
>= 217) {
3784 internalField
.Append(new BoolField
<8>(generalData
.bluetoothEnable
));
3785 internalField
.Append(new ZCharField
<10>(generalData
.bluetoothName
, "Bluetooth name"));
3788 if (IS_HORUS(board
)) {
3789 internalField
.Append(new CharField
<8>(generalData
.themeName
, true, "Theme name"));
3790 for (int i
=0; i
<5; i
++) {
3791 internalField
.Append(new CharField
<8>((char *)generalData
.themeOptionValue
[i
], true, "Theme blob"));
3797 void OpenTxGeneralData::beforeExport()
3800 if (version
>= 216) {
3802 for (int i
=0; i
<inputsCount
; i
++) {
3803 sum
+= generalData
.calibMid
[i
];
3804 if (++count
== 12) break;
3805 sum
+= generalData
.calibSpanNeg
[i
];
3806 if (++count
== 12) break;
3807 sum
+= generalData
.calibSpanPos
[i
];
3808 if (++count
== 12) break;
3812 for (int i
=0; i
<inputsCount
; i
++)
3813 sum
+= generalData
.calibMid
[i
];
3814 for (int i
=0; i
<5; i
++)
3815 sum
+= generalData
.calibSpanNeg
[i
];
3820 void OpenTxGeneralData::afterImport()
3822 if (IS_TARANIS(board
) && version
< 217) {
3823 generalData
.potConfig
[0] = GeneralSettings::POT_WITH_DETENT
;
3824 generalData
.potConfig
[1] = GeneralSettings::POT_WITH_DETENT
;