Fix doc path
[opentx.git] / radio / src / storage / eeprom_conversions.cpp
blobfed5d5bc0c5fccd0e31ab36b09759abd87338763
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 "opentx.h"
23 enum Mix216Sources {
24 MIXSRC216_NONE,
26 #if defined(PCBTARANIS)
27 MIXSRC216_FIRST_INPUT,
28 MIXSRC216_LAST_INPUT = MIXSRC216_FIRST_INPUT+MAX_INPUTS-1,
30 MIXSRC216_FIRST_LUA,
31 MIXSRC216_LAST_LUA = MIXSRC216_FIRST_LUA+(MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)-1,
32 #endif
34 MIXSRC216_Rud,
35 MIXSRC216_Ele,
36 MIXSRC216_Thr,
37 MIXSRC216_Ail,
39 MIXSRC216_FIRST_POT,
40 #if defined(PCBTARANIS)
41 MIXSRC216_POT1 = MIXSRC216_FIRST_POT,
42 MIXSRC216_POT2,
43 MIXSRC216_POT3,
44 MIXSRC216_SLIDER1,
45 MIXSRC216_SLIDER2,
46 MIXSRC216_LAST_POT = MIXSRC216_SLIDER2,
47 #else
48 MIXSRC216_P1 = MIXSRC216_FIRST_POT,
49 MIXSRC216_P2,
50 MIXSRC216_P3,
51 MIXSRC216_LAST_POT = MIXSRC216_P3,
52 #endif
54 #if defined(PCBSKY9X)
55 MIXSRC216_REa,
56 MIXSRC216_LAST_ROTARY_ENCODER = MIXSRC216_REa,
57 #endif
59 MIXSRC216_MAX,
61 MIXSRC216_CYC1,
62 MIXSRC216_CYC2,
63 MIXSRC216_CYC3,
65 MIXSRC216_TrimRud,
66 MIXSRC216_TrimEle,
67 MIXSRC216_TrimThr,
68 MIXSRC216_TrimAil,
70 MIXSRC216_FIRST_SWITCH,
72 #if defined(PCBTARANIS)
73 MIXSRC216_SA = MIXSRC216_FIRST_SWITCH,
74 MIXSRC216_SB,
75 MIXSRC216_SC,
76 MIXSRC216_SD,
77 MIXSRC216_SE,
78 MIXSRC216_SF,
79 MIXSRC216_SG,
80 MIXSRC216_SH,
81 #else
82 MIXSRC216_3POS = MIXSRC216_FIRST_SWITCH,
83 MIXSRC216_THR,
84 MIXSRC216_RUD,
85 MIXSRC216_ELE,
86 MIXSRC216_AIL,
87 MIXSRC216_GEA,
88 MIXSRC216_TRN,
89 #endif
90 MIXSRC216_FIRST_LOGICAL_SWITCH,
91 MIXSRC216_SW1 = MIXSRC216_FIRST_LOGICAL_SWITCH,
92 MIXSRC216_SW9 = MIXSRC216_SW1 + 8,
93 MIXSRC216_SWA,
94 MIXSRC216_SWB,
95 MIXSRC216_SWC,
96 MIXSRC216_LAST_LOGICAL_SWITCH = MIXSRC216_FIRST_LOGICAL_SWITCH+32-1,
98 MIXSRC216_FIRST_TRAINER,
99 MIXSRC216_LAST_TRAINER = MIXSRC216_FIRST_TRAINER+MAX_TRAINER_CHANNELS-1,
101 MIXSRC216_FIRST_CH,
102 MIXSRC216_CH1 = MIXSRC216_FIRST_CH,
103 MIXSRC216_CH2,
104 MIXSRC216_CH3,
105 MIXSRC216_CH4,
106 MIXSRC216_CH5,
107 MIXSRC216_CH6,
108 MIXSRC216_CH7,
109 MIXSRC216_CH8,
110 MIXSRC216_CH9,
111 MIXSRC216_CH10,
112 MIXSRC216_CH11,
113 MIXSRC216_CH12,
114 MIXSRC216_CH13,
115 MIXSRC216_CH14,
116 MIXSRC216_CH15,
117 MIXSRC216_CH16,
118 MIXSRC216_LAST_CH = MIXSRC216_CH1+MAX_OUTPUT_CHANNELS-1,
120 MIXSRC216_GVAR1,
121 MIXSRC216_LAST_GVAR = MIXSRC216_GVAR1+MAX_GVARS-1,
123 MIXSRC216_FIRST_TELEM,
126 enum Telemetry216Source {
127 TELEM216_NONE,
128 TELEM216_TX_VOLTAGE,
129 TELEM216_TX_TIME,
130 TELEM216_RESERVE1,
131 TELEM216_RESERVE2,
132 TELEM216_RESERVE3,
133 TELEM216_RESERVE4,
134 TELEM216_RESERVE5,
135 TELEM216_TIMER1,
136 TELEM216_TIMER2,
137 TELEM216_SWR,
138 TELEM216_RSSI_TX,
139 TELEM216_RSSI_RX,
140 TELEM216_RESERVE0,
141 TELEM216_A1,
142 TELEM216_A2,
143 TELEM216_A3,
144 TELEM216_A4,
145 TELEM216_ALT,
146 TELEM216_RPM,
147 TELEM216_FUEL,
148 TELEM216_T1,
149 TELEM216_T2,
150 TELEM216_SPEED,
151 TELEM216_DIST,
152 TELEM216_GPSALT,
153 TELEM216_CELL,
154 TELEM216_CELLS_SUM,
155 TELEM216_VFAS,
156 TELEM216_CURRENT,
157 TELEM216_CONSUMPTION,
158 TELEM216_POWER,
159 TELEM216_ACCx,
160 TELEM216_ACCy,
161 TELEM216_ACCz,
162 TELEM216_HDG,
163 TELEM216_VSPEED,
164 TELEM216_ASPEED,
165 TELEM216_DTE,
166 TELEM216_RESERVE6,
167 TELEM216_RESERVE7,
168 TELEM216_RESERVE8,
169 TELEM216_RESERVE9,
170 TELEM216_RESERVE10,
171 TELEM216_MIN_A1,
172 TELEM216_MIN_A2,
173 TELEM216_MIN_A3,
174 TELEM216_MIN_A4,
175 TELEM216_MIN_ALT,
176 TELEM216_MAX_ALT,
177 TELEM216_MAX_RPM,
178 TELEM216_MAX_T1,
179 TELEM216_MAX_T2,
180 TELEM216_MAX_SPEED,
181 TELEM216_MAX_DIST,
182 TELEM216_MAX_ASPEED,
183 TELEM216_MIN_CELL,
184 TELEM216_MIN_CELLS_SUM,
185 TELEM216_MIN_VFAS,
186 TELEM216_MAX_CURRENT,
187 TELEM216_MAX_POWER,
188 TELEM216_RESERVE11,
189 TELEM216_RESERVE12,
190 TELEM216_RESERVE13,
191 TELEM216_RESERVE14,
192 TELEM216_RESERVE15,
193 TELEM216_ACC,
194 TELEM216_GPS_TIME,
197 #if defined(CPUARM)
198 PACK(typedef struct {
199 uint8_t type:3;
200 uint8_t smooth:1;
201 uint8_t spare:4;
202 int8_t points;
203 }) CurveData_v216;
204 #endif
206 #if defined(PCBTARANIS)
207 PACK(typedef struct {
208 uint8_t srcRaw;
209 uint16_t scale;
210 uint8_t chn;
211 int8_t swtch;
212 uint16_t flightModes;
213 int8_t weight;
214 int8_t carryTrim:6;
215 uint8_t mode:2;
216 char name[LEN_EXPOMIX_NAME];
217 int8_t offset;
218 CurveRef curve;
219 uint8_t spare;
220 }) ExpoData_v216;
221 PACK(typedef struct {
222 uint32_t srcRaw:10;
223 uint32_t scale:14;
224 uint32_t chn:8;
225 int8_t swtch;
226 uint16_t flightModes;
227 int8_t weight;
228 int8_t carryTrim:6;
229 uint8_t mode:2;
230 char name[LEN_EXPOMIX_NAME];
231 int8_t offset;
232 CurveRef curve;
233 }) ExpoData_v217;
234 #else
235 PACK(typedef struct {
236 uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
237 uint8_t chn:4;
238 uint8_t curveMode:2;
239 int8_t swtch;
240 uint16_t flightModes;
241 int8_t weight;
242 char name[LEN_EXPOMIX_NAME];
243 int8_t curveParam;
244 }) ExpoData_v216;
245 typedef ExpoData_v216 ExpoData_v217;
246 #endif
248 #if defined(PCBTARANIS)
249 PACK(typedef struct {
250 int16_t min;
251 int16_t max;
252 int8_t ppmCenter;
253 int16_t offset:14;
254 uint16_t symetrical:1;
255 uint16_t revert:1;
256 char name[LEN_CHANNEL_NAME];
257 int8_t curve;
258 }) LimitData_v216;
259 #else
260 #define LimitData_v216 LimitData
261 #endif
263 #if defined(PCBTARANIS)
264 PACK(typedef struct {
265 uint8_t destCh;
266 uint16_t flightModes;
267 uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
268 uint8_t carryTrim:1;
269 uint8_t spare1:5;
270 int16_t weight;
271 int8_t swtch;
272 CurveRef curve;
273 uint8_t mixWarn:4; // mixer warning
274 uint8_t spare2:4;
275 uint8_t delayUp;
276 uint8_t delayDown;
277 uint8_t speedUp;
278 uint8_t speedDown;
279 uint8_t srcRaw;
280 int16_t offset;
281 char name[LEN_EXPOMIX_NAME];
282 uint8_t spare3;
283 }) MixData_v216;
284 PACK(typedef struct {
285 uint8_t destCh;
286 uint16_t flightModes:9;
287 uint16_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
288 uint16_t carryTrim:1;
289 uint16_t mixWarn:4; // mixer warning
290 int16_t weight;
291 uint32_t srcRaw:10;
292 int32_t offset:14;
293 int32_t swtch:8;
294 CurveRef curve;
295 uint8_t delayUp;
296 uint8_t delayDown;
297 uint8_t speedUp;
298 uint8_t speedDown;
299 char name[LEN_EXPOMIX_NAME];
300 }) MixData_v217;
301 #else
302 PACK(typedef struct {
303 uint8_t destCh:5;
304 uint8_t mixWarn:3; // mixer warning
305 uint16_t flightModes;
306 uint8_t curveMode:1;
307 uint8_t noExpo:1;
308 int8_t carryTrim:3;
309 uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
310 uint8_t spare:1;
311 int16_t weight;
312 int8_t swtch;
313 int8_t curveParam;
314 uint8_t delayUp;
315 uint8_t delayDown;
316 uint8_t speedUp;
317 uint8_t speedDown;
318 uint8_t srcRaw;
319 int16_t offset;
320 char name[LEN_EXPOMIX_NAME];
321 }) MixData_v216;
322 typedef MixData MixData_v217;
323 #endif
325 PACK(typedef struct {
326 int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
327 uint16_t start;
328 uint8_t countdownBeep:2;
329 uint8_t minuteBeep:1;
330 uint8_t persistent:2;
331 uint8_t spare:3;
332 uint16_t value;
333 }) TimerData_v216;
335 PACK(typedef struct {
336 int32_t mode:8; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
337 uint32_t start:24;
338 int32_t value:24;
339 uint32_t countdownBeep:2;
340 uint32_t minuteBeep:1;
341 uint32_t persistent:2;
342 uint32_t spare:3;
343 char name[LEN_TIMER_NAME];
344 }) TimerData_v217;
346 PACK(typedef struct {
347 int16_t trim[NUM_STICKS];
348 int8_t swtch; // swtch of phase[0] is not used
349 char name[LEN_FLIGHT_MODE_NAME];
350 uint8_t fadeIn;
351 uint8_t fadeOut;
352 int16_t rotaryEncoders[1];
353 gvar_t gvars[9];
354 }) FlightModeData_v216;
356 PACK(typedef struct { // Logical Switches data
357 int8_t v1;
358 int16_t v2;
359 int16_t v3;
360 uint8_t func;
361 uint8_t delay;
362 uint8_t duration;
363 int8_t andsw;
364 }) LogicalSwitchData_v216;
366 PACK(typedef struct { // Logical Switches data
367 uint16_t func:6;
368 int16_t v1:10;
369 int16_t v2;
370 int16_t v3;
371 uint8_t delay;
372 uint8_t duration;
373 int8_t andsw;
374 }) LogicalSwitchData_v217;
376 #if defined(PCBTARANIS)
377 PACK(typedef struct {
378 int8_t swtch;
379 uint8_t func;
380 PACK(union {
381 PACK(struct {
382 char name[8];
383 }) play;
385 PACK(struct {
386 int16_t val;
387 uint8_t mode;
388 uint8_t param;
389 int32_t spare2;
390 }) all;
392 PACK(struct {
393 int32_t val1;
394 int32_t val2;
395 }) clear;
397 uint8_t active;
398 }) CustomFunctionData_v216;
399 #else
400 PACK(typedef struct {
401 int8_t swtch;
402 uint8_t func;
403 PACK(union {
404 PACK(struct {
405 char name[6];
406 }) play;
408 PACK(struct {
409 int16_t val;
410 uint8_t mode;
411 uint8_t param;
412 int16_t spare2;
413 }) all;
415 PACK(struct {
416 int32_t val1;
417 int16_t val2;
418 }) clear;
420 uint8_t active;
421 }) CustomFunctionData_v216;
422 #endif
424 PACK(typedef struct {
425 uint8_t source;
426 uint8_t barMin; // minimum for bar display
427 uint8_t barMax; // ditto for max display (would usually = ratio)
428 }) FrSkyBarData_v216;
430 PACK(typedef struct {
431 uint8_t sources[NUM_LINE_ITEMS];
432 }) FrSkyLineData_v216;
434 typedef union {
435 FrSkyBarData_v216 bars[4];
436 FrSkyLineData_v216 lines[4];
437 } FrSkyScreenData_v216;
440 PACK(struct FrSkyChannelData_v216 {
441 uint8_t unused[7];
445 PACK(typedef struct {
446 FrSkyChannelData_v216 channels[4];
447 uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon
448 uint8_t voltsSource:7;
449 uint8_t altitudeDisplayed:1;
450 int8_t blades; // How many blades for RPMs, 0=2 blades
451 uint8_t currentSource;
452 uint8_t screensType; // 2bits per screen (None/Gauges/Numbers/Script)
453 FrSkyScreenData_v216 screens[3];
454 uint8_t varioSource;
455 int8_t varioCenterMax;
456 int8_t varioCenterMin;
457 int8_t varioMin;
458 int8_t varioMax;
459 uint8_t rssiAlarms[2];
460 uint16_t mAhPersistent:1;
461 uint16_t storedMah:15;
462 int8_t fasOffset;
463 }) FrSkyData_v216;
465 PACK(typedef struct {
466 char file[10];
467 char name[10];
468 int8_t inputs[10];
469 }) ScriptData_v216;
471 PACK(typedef struct { // Swash Ring data
472 uint8_t invertELE:1;
473 uint8_t invertAIL:1;
474 uint8_t invertCOL:1;
475 uint8_t type:5;
476 uint8_t collectiveSource;
477 uint8_t value;
478 }) SwashRingData_v216;
480 PACK(typedef struct {
481 int8_t rfProtocol;
482 uint8_t channelsStart;
483 int8_t channelsCount; // 0=8 channels
484 uint8_t failsafeMode;
485 int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
486 int8_t ppmDelay;
487 int8_t ppmFrameLength;
488 uint8_t ppmPulsePol;
489 }) ModuleData_v216;
491 #if defined(PCBTARANIS)
492 #define MODELDATA_EXTRA_216 \
493 uint8_t externalModule; \
494 uint8_t trainerMode; \
495 ModuleData_v216 moduleData[NUM_MODULES+1]; \
496 char curveNames[MAX_CURVES][6]; \
497 ScriptData_v216 scriptsData[MAX_SCRIPTS]; \
498 char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; \
499 uint8_t nPotsToWarn; \
500 int8_t potPosition[NUM_POTS+NUM_SLIDERS]; \
501 uint8_t spare[2];
502 #elif defined(PCBSKY9X)
503 #define MODELDATA_EXTRA_216 \
504 uint8_t externalModule; \
505 ModuleData_v216 moduleData[NUM_MODULES+1]; \
506 uint8_t nPotsToWarn; \
507 int8_t potPosition[NUM_POTS+NUM_SLIDERS]; \
508 uint8_t rxBattAlarms[2];
509 #endif
511 #if defined(PCBTARANIS)
512 #define MODELDATA_EXTRA_217 \
513 uint8_t spare:3; \
514 uint8_t trainerMode:3; \
515 uint8_t potsWarnMode:2; \
516 ModuleData moduleData[NUM_MODULES+1]; \
517 char curveNames[MAX_CURVES][6]; \
518 ScriptData scriptsData[MAX_SCRIPTS]; \
519 char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; \
520 uint8_t potsWarnEnabled; \
521 int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS];
522 #else
523 #define MODELDATA_EXTRA_217 \
524 uint8_t spare:6; \
525 uint8_t potsWarnMode:2; \
526 ModuleData moduleData[NUM_MODULES+1]; \
527 uint8_t potsWarnEnabled; \
528 int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]; \
529 uint8_t rxBattAlarms[2];
530 #endif
532 #if defined(PCBTARANIS) && LCD_W >= 212
533 PACK(typedef struct {
534 char name[LEN_MODEL_NAME];
535 uint8_t modelId;
536 char bitmap[LEN_BITMAP_NAME];
537 }) ModelHeader_v216;
538 #else
539 PACK(typedef struct {
540 char name[LEN_MODEL_NAME];
541 uint8_t modelId;
542 }) ModelHeader_v216;
543 #endif
545 PACK(typedef struct {
546 ModelHeader_v216 header;
547 TimerData_v216 timers[2];
548 AVR_FIELD(uint8_t protocol:3)
549 ARM_FIELD(uint8_t telemetryProtocol:3)
550 uint8_t thrTrim:1; // Enable Throttle Trim
551 AVR_FIELD(int8_t ppmNCH:4)
552 ARM_FIELD(int8_t spare2:4)
553 int8_t trimInc:3; // Trim Increments
554 uint8_t disableThrottleWarning:1;
555 ARM_FIELD(uint8_t displayChecklist:1)
556 AVR_FIELD(uint8_t pulsePol:1)
557 uint8_t extendedLimits:1;
558 uint8_t extendedTrims:1;
559 uint8_t throttleReversed:1;
560 AVR_FIELD(int8_t ppmDelay)
561 BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7
562 MixData_v216 mixData[MAX_MIXERS];
563 LimitData_v216 limitData[MAX_OUTPUT_CHANNELS];
564 ExpoData_v216 expoData[MAX_EXPOS];
566 CurveData_v216 curves[MAX_CURVES];
567 int8_t points[MAX_CURVE_POINTS];
569 LogicalSwitchData_v216 logicalSw[32];
570 CustomFunctionData_v216 customFn[MAX_SPECIAL_FUNCTIONS];
571 SwashRingData_v216 swashR;
572 FlightModeData_v216 flightModeData[MAX_FLIGHT_MODES];
574 uint8_t thrTraceSrc;
576 uint16_t switchWarningState;
577 uint8_t switchWarningEnable;
579 GVarData gvars[MAX_GVARS];
581 FrSkyData_v216 frsky;
583 MODELDATA_EXTRA_216
585 }) ModelData_v216;
587 PACK(typedef struct {
588 char name[6];
589 uint8_t popup:1;
590 uint8_t spare:7;
591 }) GVarData_v217;
593 PACK(typedef struct {
594 ModelHeader header;
595 TimerData_v217 timers[MAX_TIMERS];
596 ARM_FIELD(uint8_t telemetryProtocol:3)
597 uint8_t thrTrim:1; // Enable Throttle Trim
598 ARM_FIELD(uint8_t noGlobalFunctions:1)
599 ARM_FIELD(uint8_t displayTrims:2)
600 ARM_FIELD(uint8_t ignoreSensorIds:1)
601 int8_t trimInc:3; // Trim Increments
602 uint8_t disableThrottleWarning:1;
603 ARM_FIELD(uint8_t displayChecklist:1)
604 uint8_t extendedLimits:1;
605 uint8_t extendedTrims:1;
606 uint8_t throttleReversed:1;
607 BeepANACenter beepANACenter;
608 MixData_v217 mixData[MAX_MIXERS];
609 LimitData limitData[MAX_OUTPUT_CHANNELS];
610 ExpoData_v217 expoData[MAX_EXPOS];
612 CurveData_v216 curves[MAX_CURVES];
613 int8_t points[MAX_CURVE_POINTS];
615 LogicalSwitchData_v217 logicalSw[32];
616 CustomFunctionData_v216 customFn[MAX_SPECIAL_FUNCTIONS];
617 SwashRingData swashR;
618 FlightModeData_v216 flightModeData[MAX_FLIGHT_MODES];
620 uint8_t thrTraceSrc;
622 swarnstate_t switchWarningState;
623 swarnenable_t switchWarningEnable;
625 GVarData_v217 gvars[MAX_GVARS];
627 FrSkyTelemetryData frsky;
628 RssiAlarmData rssiAlarms;
630 MODELDATA_EXTRA_217
632 TelemetrySensor telemetrySensors[MAX_TELEMETRY_SENSORS];
634 TARANIS_PCBX9E_FIELD(uint8_t toplcdTimer)
635 }) ModelData_v217;
637 int ConvertTelemetrySource_216_to_217(int source)
639 // TELEM_TIMER3 added
640 // if (source >= TELEM_TIMER3)
641 // source += 1;
643 return source;
646 #if defined(PCBTARANIS)
647 int ConvertSwitch_216_to_217(int swtch)
649 if (swtch < 0)
650 return -ConvertSwitch_216_to_217(-swtch);
652 if (swtch > SWSRC_SF0)
653 swtch += 1;
655 if (swtch > SWSRC_SH0)
656 swtch += 1;
658 return swtch;
660 #else
661 int ConvertSwitch_216_to_217(int swtch)
663 return swtch;
665 #endif
667 int ConvertSwitch_217_to_218(int swtch)
669 // 32 additional logical switches
671 if (swtch < 0)
672 return -ConvertSwitch_217_to_218(-swtch);
674 if (swtch >= SWSRC_FIRST_LOGICAL_SWITCH+32)
675 return swtch+32;
677 return swtch;
680 int ConvertSource_216_to_217(int source)
682 #if defined(PCBX9E)
683 // SI to SR switches added
684 if (source >= MIXSRC_SI)
685 source += 10;
686 #endif
687 // Telemetry conversions
688 if (source >= MIXSRC_FIRST_TELEM)
689 source = 0;
691 return source;
694 int ConvertSource_217_to_218(int source)
696 #if defined(PCBTARANIS)
697 if (source >= MIXSRC_FIRST_LOGICAL_SWITCH + 32)
698 source += 32;
699 #endif
701 return source;
704 int ConvertGVar_216_to_217(int value)
706 if (value < -4096 + 9)
707 value += 4096 - 1024;
708 else if (value > 4095 - 9)
709 value -= 4095 - 1023;
710 return value;
713 PACK(typedef struct {
714 uint8_t version;
715 uint16_t variant;
716 CalibData calib[NUM_STICKS+NUM_POTS+NUM_SLIDERS];
717 uint16_t chkSum;
718 int8_t currModel;
719 uint8_t contrast;
720 uint8_t vBatWarn;
721 int8_t txVoltageCalibration;
722 int8_t backlightMode;
723 TrainerData trainer;
724 uint8_t view; // index of view in main screen
725 int8_t buzzerMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all
726 uint8_t fai:1;
727 int8_t beepMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all
728 uint8_t alarmsFlash:1;
729 uint8_t disableMemoryWarning:1;
730 uint8_t disableAlarmWarning:1;
731 uint8_t stickMode:2;
732 int8_t timezone:5;
733 uint8_t adjustRTC:1;
734 uint8_t inactivityTimer;
735 uint8_t telemetryBaudrate:3;
736 int8_t splashMode:3;
737 int8_t hapticMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all
738 int8_t switchesDelay;
739 uint8_t lightAutoOff;
740 uint8_t templateSetup; // RETA order for receiver channels
741 int8_t PPM_Multiplier;
742 int8_t hapticLength;
743 uint8_t reNavigation;
744 N_TARANIS_FIELD(uint8_t stickReverse)
745 int8_t beepLength:3;
746 int8_t hapticStrength:3;
747 uint8_t gpsFormat:1;
748 uint8_t unexpectedShutdown:1;
749 uint8_t speakerPitch;
750 int8_t speakerVolume;
751 int8_t vBatMin;
752 int8_t vBatMax;
754 uint8_t backlightBright;
755 int8_t txCurrentCalibration;
756 int8_t temperatureWarn;
757 uint8_t mAhWarn;
758 uint16_t mAhUsed;
759 uint32_t globalTimer;
760 int8_t temperatureCalib;
761 uint8_t bluetoothBaudrate;
762 uint8_t optrexDisplay;
763 uint8_t sticksGain;
764 uint8_t rotarySteps;
765 uint8_t countryCode;
766 uint8_t imperial;
767 char ttsLanguage[2];
768 int8_t beepVolume;
769 int8_t wavVolume;
770 int8_t varioVolume;
771 int8_t varioPitch;
772 int8_t varioRange;
773 int8_t varioRepeat;
774 int8_t backgroundVolume;
776 TARANIS_FIELD(uint8_t serial2Mode:6)
777 TARANIS_FIELD(uint8_t slidersConfig:2)
778 TARANIS_FIELD(uint8_t potsConfig)
779 TARANIS_FIELD(uint8_t backlightColor)
780 TARANIS_FIELD(swarnstate_t switchUnlockStates)
781 TARANIS_FIELD(CustomFunctionData_v216 customFn[MAX_SPECIAL_FUNCTIONS])
782 TARANIS_FIELD(swconfig_t switchConfig)
783 TARANIS_FIELD(char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME])
784 TARANIS_FIELD(char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME])
785 N_TARANIS_FIELD(CustomFunctionData_v216 customFn[MAX_SPECIAL_FUNCTIONS])
787 TARANIS_PCBX9E_FIELD(uint8_t bluetoothEnable)
788 TARANIS_PCBX9E_FIELD(char bluetoothName[LEN_BLUETOOTH_NAME])
789 }) RadioData_v216;
791 void ConvertRadioData_216_to_217(RadioData & settings)
793 RadioData_v216 * settings_v216 = (RadioData_v216 *)&settings;
794 settings_v216->version = 217;
795 #if defined(PCBTARANIS)
796 settings_v216->potsConfig = 0x05; // S1 and S2 = pots with detent
797 settings_v216->switchConfig = 0x00007bff; // 6x3POS, 1x2POS, 1xTOGGLE
798 #endif
801 void ConvertSpecialFunctions_217_to_218(CustomFunctionData * cf218, CustomFunctionData_v216 * cf216)
803 for (int i=0; i<MAX_SPECIAL_FUNCTIONS; i++) {
804 CustomFunctionData & cf = cf218[i];
805 memcpy(&cf, &cf216[i], sizeof(CustomFunctionData));
806 cf.swtch = ConvertSwitch_217_to_218(cf216[i].swtch);
807 cf.func = cf216[i].func;
808 if (cf.func == FUNC_PLAY_VALUE || cf.func == FUNC_VOLUME || (IS_ADJUST_GV_FUNC(cf.func) && cf.all.mode == FUNC_ADJUST_GVAR_SOURCE)) {
809 cf.all.val = ConvertSource_217_to_218(cf.all.val);
814 void ConvertRadioData_217_to_218(RadioData & settings)
816 RadioData_v216 settings_v217 = (RadioData_v216 &)settings;
818 settings.version = 218;
819 #if !defined(PCBTARANIS)
820 settings.stickReverse = settings_v217.stickReverse;
821 #endif
822 settings.beepLength = settings_v217.beepLength;
823 settings.hapticStrength = settings_v217.hapticStrength;
824 settings.gpsFormat = settings_v217.gpsFormat;
825 settings.unexpectedShutdown = settings_v217.unexpectedShutdown;
826 settings.speakerPitch = settings_v217.speakerPitch;
827 settings.speakerVolume = settings_v217.speakerVolume;
828 settings.vBatMin = settings_v217.vBatMin;
829 settings.vBatMax = settings_v217.vBatMax;
830 settings.backlightBright = settings_v217.backlightBright;
831 settings.globalTimer = settings_v217.globalTimer;
832 settings.bluetoothBaudrate = settings_v217.bluetoothBaudrate;
833 settings.countryCode = settings_v217.countryCode;
834 settings.imperial = settings_v217.imperial;
835 settings.ttsLanguage[0] = settings_v217.ttsLanguage[0];
836 settings.ttsLanguage[1] = settings_v217.ttsLanguage[1];
837 settings.beepVolume = settings_v217.beepVolume;
838 settings.wavVolume = settings_v217.wavVolume;
839 settings.varioVolume = settings_v217.varioVolume;
840 settings.backgroundVolume = settings_v217.backgroundVolume;
841 settings.varioPitch = settings_v217.varioPitch;
842 settings.varioRange = settings_v217.varioRange;
843 settings.varioRepeat = settings_v217.varioRepeat;
844 ConvertSpecialFunctions_217_to_218(settings.customFn, settings_v217.customFn);
846 #if defined(PCBTARANIS)
847 settings.serial2Mode = settings_v217.serial2Mode;
848 settings.slidersConfig = settings_v217.slidersConfig;
849 settings.potsConfig = settings_v217.potsConfig;
850 settings.backlightColor = settings_v217.backlightColor;
851 settings.switchUnlockStates = settings_v217.switchUnlockStates;
852 settings.switchConfig = settings_v217.switchConfig;
853 memcpy(settings.switchNames, settings_v217.switchNames, sizeof(settings.switchNames));
854 memcpy(settings.anaNames, settings_v217.anaNames, sizeof(settings.anaNames));
855 #endif
857 #if defined(PCBX9E)
858 memcpy(settings.bluetoothName, settings_v217.bluetoothName, sizeof(settings.bluetoothName));
859 #endif
861 #if defined(PCBSKY9X)
862 settings.txCurrentCalibration = settings_v217.txCurrentCalibration;
863 settings.temperatureWarn = settings_v217.temperatureWarn;
864 settings.mAhWarn = settings_v217.mAhWarn;
865 settings.mAhUsed = settings_v217.mAhUsed;
866 settings.temperatureCalib = settings_v217.temperatureCalib;
867 settings.optrexDisplay = settings_v217.optrexDisplay;
868 settings.sticksGain = settings_v217.sticksGain;
869 settings.rotarySteps = settings_v217.rotarySteps;
870 #endif
873 void ConvertModel_216_to_217(ModelData & model)
875 // Timer3 added
876 // 32bits Timers
877 // MixData reduction
878 // PPM center range
879 // Telemetry custom screens
881 assert(sizeof(ModelData_v216) <= sizeof(ModelData));
883 ModelData_v216 oldModel;
884 memcpy(&oldModel, &model, sizeof(oldModel));
885 ModelData_v217 & newModel = (ModelData_v217 &)model;
886 memset(&newModel, 0, sizeof(ModelData_v217));
888 char name[LEN_MODEL_NAME+1];
889 zchar2str(name, oldModel.header.name, LEN_MODEL_NAME);
890 TRACE("Model %s conversion from v216 to v217", name);
892 newModel.header.modelId[0] = oldModel.header.modelId;
893 memcpy(newModel.header.name, oldModel.header.name, LEN_MODEL_NAME);
894 #if defined(PCBTARANIS) && LCD_W >= 212
895 memcpy(newModel.header.bitmap, oldModel.header.bitmap, LEN_BITMAP_NAME);
896 #endif
898 for (uint8_t i=0; i<2; i++) {
899 TimerData_v217 & timer = newModel.timers[i];
900 if (oldModel.timers[i].mode >= TMRMODE_COUNT)
901 timer.mode = TMRMODE_COUNT + ConvertSwitch_216_to_217(oldModel.timers[i].mode - TMRMODE_COUNT + 1) - 1;
902 else
903 timer.mode = ConvertSwitch_216_to_217(oldModel.timers[i].mode);
904 timer.start = oldModel.timers[i].start;
905 timer.countdownBeep = oldModel.timers[i].countdownBeep;
906 timer.minuteBeep = oldModel.timers[i].minuteBeep;
907 timer.persistent = oldModel.timers[i].persistent;
908 timer.value = oldModel.timers[i].value;
910 newModel.telemetryProtocol = oldModel.telemetryProtocol;
911 newModel.thrTrim = oldModel.thrTrim;
912 newModel.trimInc = oldModel.trimInc;
913 newModel.disableThrottleWarning = oldModel.disableThrottleWarning;
914 newModel.displayChecklist = oldModel.displayChecklist;
915 newModel.extendedLimits = oldModel.extendedLimits;
916 newModel.extendedTrims = oldModel.extendedTrims;
917 newModel.throttleReversed = oldModel.throttleReversed;
918 newModel.beepANACenter = oldModel.beepANACenter;
919 for (int i=0; i<MAX_MIXERS; i++) {
920 newModel.mixData[i].destCh = oldModel.mixData[i].destCh;
921 newModel.mixData[i].flightModes = oldModel.mixData[i].flightModes;
922 newModel.mixData[i].mltpx = oldModel.mixData[i].mltpx;
923 newModel.mixData[i].carryTrim = oldModel.mixData[i].carryTrim;
924 newModel.mixData[i].mixWarn = oldModel.mixData[i].mixWarn;
925 newModel.mixData[i].weight = ConvertGVar_216_to_217(oldModel.mixData[i].weight);
926 newModel.mixData[i].swtch = ConvertSwitch_216_to_217(oldModel.mixData[i].swtch);
927 #if defined(PCBTARANIS)
928 newModel.mixData[i].curve = oldModel.mixData[i].curve;
929 #else
930 // TODO newModel.mixData[i].curveMode = oldModel.mixData[i].curveMode;
931 // TODO newModel.mixData[i].noExpo = oldModel.mixData[i].noExpo;
932 // TODO newModel.mixData[i].curveParam = oldModel.mixData[i].curveParam;
933 #endif
934 newModel.mixData[i].delayUp = oldModel.mixData[i].delayUp;
935 newModel.mixData[i].delayDown = oldModel.mixData[i].delayDown;
936 newModel.mixData[i].speedUp = oldModel.mixData[i].speedUp;
937 newModel.mixData[i].speedDown = oldModel.mixData[i].speedDown;
938 newModel.mixData[i].srcRaw = ConvertSource_216_to_217(oldModel.mixData[i].srcRaw);
939 newModel.mixData[i].offset = ConvertGVar_216_to_217(oldModel.mixData[i].offset);
940 memcpy(newModel.mixData[i].name, oldModel.mixData[i].name, sizeof(newModel.mixData[i].name));
942 for (int i=0; i<MAX_OUTPUT_CHANNELS; i++) {
943 #if defined(PCBTARANIS)
944 newModel.limitData[i].min = ConvertGVar_216_to_217(oldModel.limitData[i].min);
945 newModel.limitData[i].max = ConvertGVar_216_to_217(oldModel.limitData[i].max);
946 newModel.limitData[i].offset = ConvertGVar_216_to_217(oldModel.limitData[i].offset);
947 newModel.limitData[i].ppmCenter = oldModel.limitData[i].ppmCenter;
948 newModel.limitData[i].symetrical = oldModel.limitData[i].symetrical;
949 newModel.limitData[i].revert = oldModel.limitData[i].revert;
950 newModel.limitData[i].curve = oldModel.limitData[i].curve;
951 memcpy(newModel.limitData[i].name, oldModel.limitData[i].name, sizeof(newModel.limitData[i].name));
952 #else
953 newModel.limitData[i] = oldModel.limitData[i];
954 #endif
956 for (int i=0; i<MAX_EXPOS; i++) {
957 #if defined(PCBTARANIS)
958 newModel.expoData[i].srcRaw = ConvertSource_216_to_217(oldModel.expoData[i].srcRaw);
959 newModel.expoData[i].scale = oldModel.expoData[i].scale;
960 newModel.expoData[i].carryTrim = oldModel.expoData[i].carryTrim;
961 newModel.expoData[i].curve = oldModel.expoData[i].curve;
962 newModel.expoData[i].offset = oldModel.expoData[i].offset;
963 #else
964 newModel.expoData[i].curveMode = oldModel.expoData[i].curveMode;
965 newModel.expoData[i].curveParam = oldModel.expoData[i].curveParam;
966 #endif
967 newModel.expoData[i].chn = oldModel.expoData[i].chn;
968 newModel.expoData[i].swtch = ConvertSwitch_216_to_217(oldModel.expoData[i].swtch);
969 newModel.expoData[i].flightModes = oldModel.expoData[i].flightModes;
970 newModel.expoData[i].weight = oldModel.expoData[i].weight;
971 newModel.expoData[i].mode = oldModel.expoData[i].mode;
972 memcpy(newModel.expoData[i].name, oldModel.expoData[i].name, sizeof(newModel.expoData[i].name));
974 memcpy(newModel.curves, oldModel.curves, sizeof(newModel.curves));
975 memcpy(newModel.points, oldModel.points, sizeof(newModel.points));
976 for (int i=0; i<32; i++) {
977 LogicalSwitchData_v217 & sw = newModel.logicalSw[i];
978 sw.func = oldModel.logicalSw[i].func;
979 sw.v1 = oldModel.logicalSw[i].v1;
980 sw.v2 = oldModel.logicalSw[i].v2;
981 sw.v3 = oldModel.logicalSw[i].v3;
982 sw.delay = oldModel.logicalSw[i].delay;
983 sw.duration = oldModel.logicalSw[i].duration;
984 uint8_t cstate = lswFamily(sw.func);
985 if (cstate == LS_FAMILY_OFS || cstate == LS_FAMILY_COMP || cstate == LS_FAMILY_DIFF) {
986 sw.v1 = ConvertSource_216_to_217((uint8_t)sw.v1);
987 if (cstate == LS_FAMILY_COMP) {
988 sw.v2 = ConvertSource_216_to_217((uint8_t)sw.v2);
991 else if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
992 sw.v1 = ConvertSwitch_216_to_217(sw.v1);
993 sw.v2 = ConvertSwitch_216_to_217(sw.v2);
995 else if (cstate == LS_FAMILY_EDGE) {
996 sw.v1 = ConvertSwitch_216_to_217(sw.v1);
998 sw.andsw = ConvertSwitch_216_to_217(sw.andsw);
1000 for (int i=0; i<MAX_SPECIAL_FUNCTIONS; i++) {
1001 CustomFunctionData_v216 & fn = newModel.customFn[i];
1002 fn = oldModel.customFn[i];
1003 fn.swtch = ConvertSwitch_216_to_217(fn.swtch);
1004 if (fn.func == FUNC_PLAY_VALUE || fn.func == FUNC_VOLUME || (IS_ADJUST_GV_FUNC(fn.func) && fn.all.mode == FUNC_ADJUST_GVAR_SOURCE)) {
1005 fn.all.val = ConvertSource_216_to_217(fn.all.val);
1009 newModel.swashR.collectiveSource = ConvertSource_216_to_217(newModel.swashR.collectiveSource);
1010 // TODO other fields
1012 for (int i=0; i<MAX_FLIGHT_MODES; i++) {
1013 newModel.flightModeData[i] = oldModel.flightModeData[i];
1014 newModel.flightModeData[i].swtch = ConvertSwitch_216_to_217(oldModel.flightModeData[i].swtch);
1017 newModel.thrTraceSrc = oldModel.thrTraceSrc;
1018 newModel.switchWarningState = oldModel.switchWarningState;
1019 newModel.switchWarningEnable = oldModel.switchWarningEnable;
1020 memcpy(newModel.gvars, oldModel.gvars, sizeof(newModel.gvars));
1022 memcpy(&newModel.rssiAlarms, &oldModel.frsky.rssiAlarms, sizeof(newModel.rssiAlarms));
1024 for (int i=0; i<NUM_MODULES+1; i++) {
1025 newModel.moduleData[i].type = 0;
1026 newModel.moduleData[i].rfProtocol = oldModel.moduleData[i].rfProtocol;
1027 newModel.moduleData[i].channelsStart = oldModel.moduleData[i].channelsStart;
1028 newModel.moduleData[i].channelsCount = oldModel.moduleData[i].channelsCount;
1029 newModel.moduleData[i].failsafeMode = oldModel.moduleData[i].failsafeMode + 1;
1030 for (int j=0; j<MAX_OUTPUT_CHANNELS; j++) {
1031 newModel.moduleData[i].failsafeChannels[j] = oldModel.moduleData[i].failsafeChannels[j];
1033 newModel.moduleData[i].ppm.delay = oldModel.moduleData[i].ppmDelay;
1034 newModel.moduleData[i].ppm.frameLength = oldModel.moduleData[i].ppmFrameLength;
1035 newModel.moduleData[i].ppm.pulsePol = oldModel.moduleData[i].ppmPulsePol;
1038 #if defined(PCBTARANIS)
1039 newModel.moduleData[INTERNAL_MODULE].type = MODULE_TYPE_XJT;
1040 #endif
1041 newModel.moduleData[EXTERNAL_MODULE].type = oldModel.externalModule;
1043 #if defined(PCBTARANIS)
1044 newModel.trainerMode = oldModel.trainerMode;
1045 // TODO memcpy(newModel.scriptsData, oldModel.scriptsData, sizeof(newModel.scriptsData));
1046 memcpy(newModel.curveNames, oldModel.curveNames, sizeof(newModel.curveNames));
1047 memcpy(newModel.inputNames, oldModel.inputNames, sizeof(newModel.inputNames));
1048 #endif
1049 newModel.potsWarnMode = oldModel.nPotsToWarn >> 6;
1050 newModel.potsWarnEnabled = oldModel.nPotsToWarn & 0x1f;
1051 memcpy(newModel.potsWarnPosition, oldModel.potPosition, sizeof(newModel.potsWarnPosition));
1054 void ConvertModel_217_to_218(ModelData & model)
1056 assert(sizeof(ModelData_v217) <= sizeof(ModelData));
1058 ModelData_v217 oldModel;
1059 memcpy(&oldModel, &model, sizeof(oldModel));
1060 ModelData & newModel = model;
1061 memset(&newModel, 0, sizeof(ModelData));
1063 char name[LEN_MODEL_NAME+1];
1064 zchar2str(name, oldModel.header.name, LEN_MODEL_NAME);
1065 TRACE("Model %s conversion from v217 to v218", name);
1067 newModel.header = oldModel.header;
1068 for (uint8_t i=0; i<MAX_TIMERS; i++) {
1069 if (oldModel.timers[i].mode >= TMRMODE_COUNT)
1070 newModel.timers[i].mode = TMRMODE_COUNT + ConvertSwitch_217_to_218(oldModel.timers[i].mode - TMRMODE_COUNT + 1) - 1;
1071 else
1072 newModel.timers[i].mode = ConvertSwitch_217_to_218(oldModel.timers[i].mode);
1073 if (oldModel.timers[i].mode)
1074 TRACE("timer mode %d => %d", oldModel.timers[i].mode, newModel.timers[i].mode);
1075 newModel.timers[i].start = oldModel.timers[i].start;
1076 newModel.timers[i].value = oldModel.timers[i].value;
1077 newModel.timers[i].countdownBeep = oldModel.timers[i].countdownBeep;
1078 newModel.timers[i].minuteBeep = oldModel.timers[i].minuteBeep;
1079 newModel.timers[i].persistent = oldModel.timers[i].persistent;
1080 memcpy(newModel.timers[i].name, oldModel.timers[i].name, sizeof(newModel.timers[i].name));
1082 newModel.telemetryProtocol = oldModel.telemetryProtocol;
1083 newModel.thrTrim = oldModel.thrTrim;
1084 newModel.noGlobalFunctions = oldModel.noGlobalFunctions;
1085 newModel.displayTrims = oldModel.displayTrims;
1086 newModel.ignoreSensorIds = oldModel.ignoreSensorIds;
1087 newModel.trimInc = oldModel.trimInc;
1088 newModel.disableThrottleWarning = oldModel.disableThrottleWarning;
1089 newModel.displayChecklist = oldModel.displayChecklist;
1090 newModel.extendedLimits = oldModel.extendedLimits;
1091 newModel.extendedTrims = oldModel.extendedTrims;
1092 newModel.throttleReversed = oldModel.throttleReversed;
1093 newModel.beepANACenter = oldModel.beepANACenter;
1094 for (int i=0; i<MAX_MIXERS; i++) {
1095 newModel.mixData[i].destCh = oldModel.mixData[i].destCh;
1096 newModel.mixData[i].flightModes = oldModel.mixData[i].flightModes;
1097 newModel.mixData[i].mltpx = oldModel.mixData[i].mltpx;
1098 newModel.mixData[i].carryTrim = oldModel.mixData[i].carryTrim;
1099 newModel.mixData[i].mixWarn = oldModel.mixData[i].mixWarn;
1100 newModel.mixData[i].weight = oldModel.mixData[i].weight;
1101 newModel.mixData[i].swtch = ConvertSwitch_217_to_218(oldModel.mixData[i].swtch);
1102 #if defined(PCBTARANIS)
1103 newModel.mixData[i].curve = oldModel.mixData[i].curve;
1104 #else
1105 // newModel.mixData[i].curveMode = oldModel.mixData[i].curveMode;
1106 // newModel.mixData[i].noExpo = oldModel.mixData[i].noExpo;
1107 // newModel.mixData[i].curveParam = oldModel.mixData[i].curveParam;
1108 #endif
1109 newModel.mixData[i].delayUp = oldModel.mixData[i].delayUp;
1110 newModel.mixData[i].delayDown = oldModel.mixData[i].delayDown;
1111 newModel.mixData[i].speedUp = oldModel.mixData[i].speedUp;
1112 newModel.mixData[i].speedDown = oldModel.mixData[i].speedDown;
1113 newModel.mixData[i].srcRaw = ConvertSource_217_to_218(oldModel.mixData[i].srcRaw);
1114 newModel.mixData[i].offset = oldModel.mixData[i].offset;
1115 memcpy(newModel.mixData[i].name, oldModel.mixData[i].name, sizeof(newModel.mixData[i].name));
1117 for (int i=0; i<MAX_OUTPUT_CHANNELS; i++) {
1118 newModel.limitData[i] = oldModel.limitData[i];
1119 #if defined(PCBTARANIS)
1120 if (newModel.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT || newModel.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_XJT) {
1121 newModel.limitData[i].ppmCenter = (oldModel.limitData[i].ppmCenter * 612) / 1024;
1123 #endif
1125 for (int i=0; i<MAX_EXPOS; i++) {
1126 #if defined(PCBTARANIS)
1127 newModel.expoData[i].srcRaw = ConvertSource_217_to_218(oldModel.expoData[i].srcRaw);
1128 newModel.expoData[i].scale = oldModel.expoData[i].scale;
1129 newModel.expoData[i].carryTrim = oldModel.expoData[i].carryTrim;
1130 newModel.expoData[i].curve = oldModel.expoData[i].curve;
1131 newModel.expoData[i].offset = oldModel.expoData[i].offset;
1132 #else
1133 // TODO newModel.expoData[i].curveMode = oldModel.expoData[i].curveMode;
1134 // TODO newModel.expoData[i].curveParam = oldModel.expoData[i].curveParam;
1135 #endif
1136 newModel.expoData[i].chn = oldModel.expoData[i].chn;
1137 newModel.expoData[i].swtch = ConvertSwitch_217_to_218(oldModel.expoData[i].swtch);
1138 newModel.expoData[i].flightModes = oldModel.expoData[i].flightModes;
1139 newModel.expoData[i].weight = oldModel.expoData[i].weight;
1140 newModel.expoData[i].mode = oldModel.expoData[i].mode;
1141 memcpy(newModel.expoData[i].name, oldModel.expoData[i].name, sizeof(newModel.expoData[i].name));
1143 for (int i=0; i<MAX_CURVES; i++) {
1144 #if defined(PCBTARANIS)
1145 newModel.curves[i].type = oldModel.curves[i].type;
1146 newModel.curves[i].smooth = oldModel.curves[i].smooth;
1147 newModel.curves[i].points = oldModel.curves[i].points;
1148 memcpy(newModel.curves[i].name, oldModel.curveNames[i], sizeof(newModel.curves[i].name));
1149 #else
1150 // TODO newModel.curves[i] = oldModel.curves[i];
1151 #endif
1153 memcpy(newModel.points, oldModel.points, sizeof(newModel.points));
1154 for (int i=0; i<32; i++) {
1155 LogicalSwitchData & sw = newModel.logicalSw[i];
1156 sw.func = oldModel.logicalSw[i].func;
1157 sw.v1 = oldModel.logicalSw[i].v1;
1158 sw.v2 = oldModel.logicalSw[i].v2;
1159 sw.v3 = oldModel.logicalSw[i].v3;
1160 newModel.logicalSw[i].andsw = ConvertSwitch_217_to_218(oldModel.logicalSw[i].andsw);
1161 sw.delay = oldModel.logicalSw[i].delay;
1162 sw.duration = oldModel.logicalSw[i].duration;
1163 uint8_t cstate = lswFamily(sw.func);
1164 if (cstate == LS_FAMILY_OFS || cstate == LS_FAMILY_COMP || cstate == LS_FAMILY_DIFF) {
1165 sw.v1 = ConvertSource_217_to_218((uint8_t)sw.v1);
1166 if (cstate == LS_FAMILY_COMP) {
1167 sw.v2 = ConvertSource_217_to_218((uint8_t)sw.v2);
1170 else if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
1171 sw.v1 = ConvertSwitch_217_to_218(sw.v1);
1172 sw.v2 = ConvertSwitch_217_to_218(sw.v2);
1174 else if (cstate == LS_FAMILY_EDGE) {
1175 sw.v1 = ConvertSwitch_217_to_218(sw.v1);
1178 ConvertSpecialFunctions_217_to_218(newModel.customFn, oldModel.customFn);
1179 newModel.swashR = oldModel.swashR;
1180 for (int i=0; i<MAX_FLIGHT_MODES; i++) {
1181 memcpy(newModel.flightModeData[i].trim, oldModel.flightModeData[i].trim, sizeof(newModel.flightModeData[i].trim));
1182 memcpy(newModel.flightModeData[i].name, oldModel.flightModeData[i].name, sizeof(newModel.flightModeData[i].name));
1183 newModel.flightModeData[i].swtch = ConvertSwitch_217_to_218(oldModel.flightModeData[i].swtch);
1184 newModel.flightModeData[i].fadeIn = oldModel.flightModeData[i].fadeIn;
1185 newModel.flightModeData[i].fadeOut = oldModel.flightModeData[i].fadeOut;
1186 #if defined(PCBSKY9X)
1187 memcpy(newModel.flightModeData[i].rotaryEncoders, oldModel.flightModeData[i].rotaryEncoders, sizeof(newModel.flightModeData[i].rotaryEncoders));
1188 #endif
1189 memcpy(newModel.flightModeData[i].gvars, oldModel.flightModeData[i].gvars, sizeof(newModel.flightModeData[i].gvars));
1191 newModel.thrTraceSrc = oldModel.thrTraceSrc;
1192 newModel.switchWarningState = oldModel.switchWarningState;
1193 newModel.switchWarningEnable = oldModel.switchWarningEnable;
1194 for (int i=0; i<MAX_GVARS; i++) {
1195 memcpy(newModel.gvars[i].name, oldModel.gvars[i].name, sizeof(newModel.gvars[i].name));
1196 newModel.gvars[i].popup = oldModel.gvars[i].popup;
1198 newModel.frsky = oldModel.frsky;
1199 for (int i=0; i<MAX_TELEMETRY_SCREENS; i++) {
1200 if (((oldModel.frsky.screensType >> (2*i)) & 0x03) == TELEMETRY_SCREEN_TYPE_VALUES) {
1201 for (int j = 0; j < 4; j++) {
1202 for (int k = 0; k < NUM_LINE_ITEMS; k++) {
1203 newModel.frsky.screens[i].lines[j].sources[k] = ConvertSource_217_to_218(oldModel.frsky.screens[i].lines[j].sources[k]);
1207 else if (((oldModel.frsky.screensType >> (2*i)) & 0x03) == TELEMETRY_SCREEN_TYPE_GAUGES) {
1208 for (int j = 0; j < 4; j++) {
1209 newModel.frsky.screens[i].bars[j].source = ConvertSource_217_to_218(oldModel.frsky.screens[i].bars[j].source);
1213 for (int i=0; i<NUM_MODULES+1; i++) {
1214 newModel.moduleData[i] = oldModel.moduleData[i];
1216 #if defined(PCBTARANIS)
1217 newModel.trainerMode = oldModel.trainerMode;
1218 memcpy(newModel.scriptsData, oldModel.scriptsData, sizeof(newModel.scriptsData));
1219 memcpy(newModel.inputNames, oldModel.inputNames, sizeof(newModel.inputNames));
1220 #endif
1221 newModel.potsWarnMode = oldModel.potsWarnMode;
1222 newModel.potsWarnEnabled = oldModel.potsWarnEnabled;
1223 memcpy(newModel.potsWarnPosition, oldModel.potsWarnPosition, sizeof(newModel.potsWarnPosition));
1224 for (uint8_t i=0; i<MAX_TELEMETRY_SENSORS; i++) {
1225 newModel.telemetrySensors[i] = oldModel.telemetrySensors[i];
1226 if (newModel.telemetrySensors[i].unit > UNIT_WATTS)
1227 newModel.telemetrySensors[i].unit += 1;
1229 #if defined(PCBX9E)
1230 newModel.toplcdTimer = oldModel.toplcdTimer;
1231 #endif
1234 void ConvertModel(int id, int version)
1236 eeLoadModelData(id);
1238 if (version == 216) {
1239 version = 217;
1240 ConvertModel_216_to_217(g_model);
1242 if (version == 217) {
1243 version = 218;
1244 ConvertModel_217_to_218(g_model);
1247 uint8_t currModel = g_eeGeneral.currModel;
1248 g_eeGeneral.currModel = id;
1249 storageDirty(EE_MODEL);
1250 storageCheck(true);
1251 g_eeGeneral.currModel = currModel;
1254 bool eeConvert()
1256 const char *msg = NULL;
1258 if (g_eeGeneral.version == 216) {
1259 msg = PSTR("EEprom Data v216");
1261 else if (g_eeGeneral.version == 217) {
1262 msg = PSTR("EEprom Data v217");
1264 else {
1265 return false;
1268 int conversionVersionStart = g_eeGeneral.version;
1270 // Information to the user and wait for key press
1271 #if defined(PCBSKY9X)
1272 g_eeGeneral.optrexDisplay = 0;
1273 #endif
1274 g_eeGeneral.backlightMode = e_backlight_mode_on;
1275 g_eeGeneral.backlightBright = 0;
1276 g_eeGeneral.contrast = 25;
1278 ALERT(STR_STORAGE_WARNING, msg, AU_BAD_RADIODATA);
1280 RAISE_ALERT(STR_STORAGE_WARNING, STR_EEPROM_CONVERTING, NULL, AU_NONE);
1282 // General Settings conversion
1283 eeLoadGeneralSettingsData();
1284 int version = conversionVersionStart;
1285 if (version == 216) {
1286 version = 217;
1287 ConvertRadioData_216_to_217(g_eeGeneral);
1289 if (version == 217) {
1290 version = 218;
1291 ConvertRadioData_217_to_218(g_eeGeneral);
1293 storageDirty(EE_GENERAL);
1294 storageCheck(true);
1296 #if defined(COLORLCD)
1297 #elif LCD_W >= 212
1298 lcdDrawRect(60, 6*FH+4, 132, 3);
1299 #else
1300 lcdDrawRect(10, 6*FH+4, 102, 3);
1301 #endif
1303 // Models conversion
1304 for (uint8_t id=0; id<MAX_MODELS; id++) {
1305 #if defined(COLORLCD)
1306 #elif LCD_W >= 212
1307 lcdDrawSolidHorizontalLine(61, 6*FH+5, 10+id*2, FORCE);
1308 #else
1309 lcdDrawSolidHorizontalLine(11, 6*FH+5, 10+(id*3)/2, FORCE);
1310 #endif
1311 lcdRefresh();
1312 if (eeModelExists(id)) {
1313 ConvertModel(id, conversionVersionStart);
1318 return true;