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