Fix doc path
[opentx.git] / radio / src / datastructs.h
blobb9f422626280d2aa39b4d6aaa1bf85e0377715df
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 // No include guards here, this file may be included many times in different namespaces
22 // i.e. BACKUP RAM Backup/Restore functions
24 #include <inttypes.h>
26 #include "board.h"
27 #include "dataconstants.h"
28 #include "definitions.h"
30 #if defined(CPUARM)
31 #define ARM_FIELD(x) x;
32 #define AVR_FIELD(x)
33 #else
34 #define ARM_FIELD(x)
35 #define AVR_FIELD(x) x;
36 #endif
38 #if defined(PCBSTD)
39 #define N_PCBSTD_FIELD(x)
40 #else
41 #define N_PCBSTD_FIELD(x) x;
42 #endif
44 #if defined(PCBTARANIS)
45 #define N_TARANIS_FIELD(x)
46 #define TARANIS_FIELD(x) x;
47 #else
48 #define N_TARANIS_FIELD(x) x;
49 #define TARANIS_FIELD(x)
50 #endif
52 #if defined(PCBX9E)
53 #define TARANIS_PCBX9E_FIELD(x) x;
54 #else
55 #define TARANIS_PCBX9E_FIELD(x)
56 #endif
58 #if defined(PCBHORUS)
59 #define N_HORUS_FIELD(x)
60 #define HORUS_FIELD(x) x;
61 #else
62 #define N_HORUS_FIELD(x) x;
63 #define HORUS_FIELD(x)
64 #endif
66 #if defined(BACKUP)
67 #define NOBACKUP(...)
68 #else
69 #define NOBACKUP(...) __VA_ARGS__
70 #endif
72 #if defined(PCBTARANIS) || defined(PCBHORUS)
73 typedef uint16_t source_t;
74 #else
75 typedef uint8_t source_t;
76 #endif
79 * Mixer structure
82 #if defined(CPUARM)
83 PACK(struct CurveRef {
84 uint8_t type;
85 int8_t value;
86 });
88 PACK(struct MixData {
89 int16_t weight:11; // GV1=-1024, -GV1=1023
90 uint16_t destCh:5;
91 uint16_t srcRaw:10; // srcRaw=0 means not used
92 uint16_t carryTrim:1;
93 uint16_t mixWarn:2; // mixer warning
94 uint16_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
95 uint16_t spare:1;
96 int32_t offset:14;
97 int32_t swtch:9;
98 uint32_t flightModes:9;
99 CurveRef curve;
100 uint8_t delayUp;
101 uint8_t delayDown;
102 uint8_t speedUp;
103 uint8_t speedDown;
104 NOBACKUP(char name[LEN_EXPOMIX_NAME]);
106 #elif defined(CPUM2560) || defined(CPUM2561)
107 PACK(struct MixData {
108 uint8_t destCh:4; // 0, 1..MAX_OUTPUT_CHANNELS
109 uint8_t curveMode:1; // O=curve, 1=differential
110 uint8_t noExpo:1;
111 uint8_t weightMode:1;
112 uint8_t offsetMode:1;
113 uint8_t srcRaw;
114 int8_t weight;
115 int8_t swtch;
116 uint8_t flightModes;
117 uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
118 int8_t carryTrim:3;
119 uint8_t mixWarn:2; // mixer warning
120 uint8_t spare:1;
121 uint8_t delayUp:4;
122 uint8_t delayDown:4;
123 uint8_t speedUp:4;
124 uint8_t speedDown:4;
125 int8_t curveParam;
126 int8_t offset;
128 #else
129 PACK(struct MixData {
130 uint8_t destCh:4; // 0, 1..MAX_OUTPUT_CHANNELS
131 uint8_t curveMode:1; // O=curve, 1=differential
132 uint8_t noExpo:1;
133 uint8_t weightMode:1;
134 uint8_t offsetMode:1;
135 int8_t weight;
136 int8_t swtch:6;
137 uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
138 uint8_t flightModes:5;
139 int8_t carryTrim:3;
140 uint8_t srcRaw:6;
141 uint8_t mixWarn:2; // mixer warning
142 uint8_t delayUp:4;
143 uint8_t delayDown:4;
144 uint8_t speedUp:4;
145 uint8_t speedDown:4;
146 int8_t curveParam;
147 int8_t offset;
149 #endif
152 * Expo/Input structure
155 #if defined(CPUARM)
156 PACK(struct ExpoData {
157 uint16_t mode:2;
158 uint16_t scale:14;
159 uint16_t srcRaw:10;
160 int16_t carryTrim:6;
161 uint32_t chn:5;
162 int32_t swtch:9;
163 uint32_t flightModes:9;
164 int32_t weight:8;
165 int32_t spare:1;
166 NOBACKUP(char name[LEN_EXPOMIX_NAME]);
167 int8_t offset;
168 CurveRef curve;
170 #elif defined(CPUM2560) || defined(CPUM2561)
171 PACK(struct ExpoData {
172 uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
173 uint8_t chn:2;
174 uint8_t curveMode:1;
175 uint8_t spare:3;
176 uint8_t flightModes;
177 int8_t swtch;
178 uint8_t weight;
179 int8_t curveParam;
181 #else
182 PACK(struct ExpoData {
183 uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
184 int8_t swtch:6;
185 uint8_t chn:2;
186 uint8_t flightModes:5;
187 uint8_t curveMode:1;
188 uint8_t weight; // One spare bit here (used for GVARS)
189 int8_t curveParam;
191 #endif
194 * Limit structure
197 #if defined(CPUARM)
198 PACK(struct LimitData {
199 int32_t min:11;
200 int32_t max:11;
201 int32_t ppmCenter:10;
202 int16_t offset:11;
203 uint16_t symetrical:1;
204 uint16_t revert:1;
205 uint16_t spare:3;
206 int8_t curve;
207 NOBACKUP(char name[LEN_CHANNEL_NAME]);
209 #else
210 PACK(struct LimitData {
211 int8_t min;
212 int8_t max;
213 int8_t ppmCenter;
214 int16_t offset:14;
215 uint16_t symetrical:1;
216 uint16_t revert:1;
218 #endif
221 * LogicalSwitch structure
224 #if defined(CPUARM)
225 PACK(struct LogicalSwitchData {
226 uint8_t func;
227 int32_t v1:10;
228 int32_t v3:10;
229 int32_t andsw:9; // TODO rename to xswtch
230 uint32_t andswtype:1; // TODO rename to xswtchType (AND / OR)
231 uint32_t spare:2; // anything else needed?
232 int16_t v2;
233 uint8_t delay;
234 uint8_t duration;
236 #else
237 PACK(struct LogicalSwitchData {
238 int8_t v1; //input
239 int8_t v2; //offset
240 uint8_t func:4;
241 uint8_t andsw:4;
243 #endif
246 * SpecialFunction structure
249 #if defined(CPUARM)
251 #if defined(PCBTARANIS)
252 #define CFN_SPARE_TYPE int32_t
253 #else
254 #define CFN_SPARE_TYPE int16_t
255 #endif
257 PACK(struct CustomFunctionData {
258 int16_t swtch:9;
259 uint16_t func:7;
260 PACK(union {
261 NOBACKUP(PACK(struct {
262 char name[LEN_FUNCTION_NAME];
263 }) play);
265 PACK(struct {
266 int16_t val;
267 uint8_t mode;
268 uint8_t param;
269 NOBACKUP(CFN_SPARE_TYPE spare);
270 }) all;
272 NOBACKUP(PACK(struct {
273 int32_t val1;
274 NOBACKUP(CFN_SPARE_TYPE val2);
275 }) clear);
277 uint8_t active;
279 #elif defined(CPUM2560)
280 PACK(struct CustomFunctionData {
281 int8_t swtch;
282 uint8_t func;
283 uint8_t mode:2;
284 uint8_t param:4;
285 uint8_t active:1;
286 uint8_t spare:1;
287 uint8_t value;
289 #else
290 PACK(struct CustomFunctionData {
291 PACK(union {
292 PACK(struct {
293 int16_t swtch:6;
294 uint16_t func:4;
295 uint16_t mode:2;
296 uint16_t param:3;
297 uint16_t active:1;
298 }) gvar;
300 PACK(struct {
301 int16_t swtch:6;
302 uint16_t func:4;
303 uint16_t param:4;
304 uint16_t spare:1;
305 uint16_t active:1;
306 }) all;
308 uint8_t value;
310 #endif
313 * FlightMode structure
316 #if defined(CPUARM)
317 PACK(struct trim_t {
318 int16_t value:11;
319 uint16_t mode:5;
321 #else
322 typedef int16_t trim_t;
323 #endif
325 typedef int16_t gvar_t;
327 #if MAX_ROTARY_ENCODERS > 0
328 #define FLIGHT_MODE_ROTARY_ENCODERS_FIELD int16_t rotaryEncoders[MAX_ROTARY_ENCODERS];
329 #else
330 #define FLIGHT_MODE_ROTARY_ENCODERS_FIELD
331 #endif
333 #if defined(CPUARM)
334 PACK(struct FlightModeData {
335 trim_t trim[NUM_TRIMS];
336 NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
337 int16_t swtch:9; // swtch of phase[0] is not used
338 int16_t spare:7;
339 uint8_t fadeIn;
340 uint8_t fadeOut;
341 FLIGHT_MODE_ROTARY_ENCODERS_FIELD
342 gvar_t gvars[MAX_GVARS];
344 #elif !defined(PCBSTD)
345 PACK(struct FlightModeData {
346 trim_t trim[NUM_STICKS];
347 int8_t swtch; // swtch of phase[0] is not used
348 NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
349 uint8_t fadeIn:4;
350 uint8_t fadeOut:4;
351 FLIGHT_MODE_ROTARY_ENCODERS_FIELD
352 gvar_t gvars[MAX_GVARS];
354 #else
355 PACK(struct FlightModeData {
356 int8_t trim[NUM_STICKS];
357 int8_t trim_ext; // 2 extra bits per trim (10bits)
358 int8_t swtch; // swtch of phase[0] is not used
359 NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
360 uint8_t fadeIn:4;
361 uint8_t fadeOut:4;
363 #endif
366 * Curve structure
369 #if defined(CPUARM)
370 PACK(struct CurveData {
371 uint8_t type:1;
372 uint8_t smooth:1;
373 int8_t points:6; // describes number of points - 5
374 NOBACKUP(char name[LEN_CURVE_NAME]);
376 #else
377 typedef int8_t CurveData;
378 #endif
381 * GVar structure
384 #if !defined(PCBSTD)
385 PACK(struct GVarData {
386 NOBACKUP(char name[LEN_GVAR_NAME]);
387 uint32_t min:12;
388 uint32_t max:12;
389 uint32_t popup:1;
390 uint32_t prec:1;
391 uint32_t unit:2;
392 uint32_t spare:4;
394 #endif
397 * Timer structure
400 #if defined(CPUARM)
401 PACK(struct TimerData {
402 int32_t mode:9; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
403 uint32_t start:23;
404 int32_t value:24;
405 uint32_t countdownBeep:2;
406 uint32_t minuteBeep:1;
407 uint32_t persistent:2;
408 int32_t countdownStart:2;
409 uint32_t direction:1;
410 NOBACKUP(char name[LEN_TIMER_NAME]);
412 #elif defined(CPUM2560)
413 PACK(struct TimerData {
414 int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
415 uint16_t start;
416 uint8_t countdownBeep:2;
417 uint8_t minuteBeep:1;
418 uint8_t persistent:2;
419 uint8_t countdownStart:3;
420 uint16_t value;
422 #else
423 PACK(struct TimerData {
424 int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
425 uint16_t start:12;
426 uint16_t countdownBeep:1;
427 uint16_t minuteBeep:1;
428 uint16_t spare:2;
430 #endif
433 * Swash Ring structure
436 #if defined(VIRTUAL_INPUTS)
437 PACK(struct SwashRingData {
438 uint8_t type;
439 uint8_t value;
440 uint8_t collectiveSource;
441 uint8_t aileronSource;
442 uint8_t elevatorSource;
443 int8_t collectiveWeight;
444 int8_t aileronWeight;
445 int8_t elevatorWeight;
447 #else
448 PACK(struct SwashRingData {
449 uint8_t invertELE:1;
450 uint8_t invertAIL:1;
451 uint8_t invertCOL:1;
452 uint8_t type:5;
453 uint8_t collectiveSource;
454 uint8_t value;
456 #endif
458 #if MAX_SCRIPTS > 0
459 union ScriptDataInput {
460 int16_t value;
461 source_t source;
464 PACK(struct ScriptData {
465 char file[LEN_SCRIPT_FILENAME];
466 char name[LEN_SCRIPT_NAME];
467 ScriptDataInput inputs[MAX_SCRIPT_INPUTS];
469 #endif
472 * Frsky Telemetry structure
474 #if defined(CPUARM)
475 PACK(struct RssiAlarmData {
476 int8_t disabled:1;
477 int8_t spare:1;
478 int8_t warning:6;
479 int8_t spare2:2;
480 int8_t critical:6;
481 inline int8_t getWarningRssi() {return 45 + warning;}
482 inline int8_t getCriticalRssi() {return 42 + critical;}
484 #else
485 PACK(struct FrSkyRSSIAlarm {
486 int8_t level:2;
487 int8_t value:6;
489 #endif
491 #if defined(CPUARM)
492 typedef int16_t ls_telemetry_value_t;
493 #else
494 typedef uint8_t ls_telemetry_value_t;
495 #endif
497 #if !defined(COLORLCD)
498 PACK(struct FrSkyBarData {
499 source_t source;
500 ls_telemetry_value_t barMin; // minimum for bar display
501 ls_telemetry_value_t barMax; // ditto for max display (would usually = ratio)
504 PACK(struct FrSkyLineData {
505 source_t sources[NUM_LINE_ITEMS];
508 #if defined(PCBTARANIS)
509 PACK(struct TelemetryScriptData {
510 char file[LEN_SCRIPT_FILENAME];
511 int16_t inputs[MAX_TELEM_SCRIPT_INPUTS];
513 #endif
515 union FrSkyScreenData {
516 FrSkyBarData bars[4];
517 FrSkyLineData lines[4];
518 #if defined(PCBTARANIS)
519 TelemetryScriptData script;
520 #endif
522 #endif
524 #if defined(COLORLCD)
525 PACK(struct FrSkyTelemetryData { // TODO EEPROM change, rename to VarioData
526 uint8_t varioSource:7;
527 uint8_t varioCenterSilent:1;
528 int8_t varioCenterMax;
529 int8_t varioCenterMin;
530 int8_t varioMin;
531 int8_t varioMax;
533 #elif defined(CPUARM)
534 // TODO remove this also on Taranis
535 PACK(struct FrSkyTelemetryData {
536 uint8_t voltsSource;
537 uint8_t altitudeSource;
538 uint8_t screensType; // 2bits per screen (None/Gauges/Numbers/Script)
539 FrSkyScreenData screens[MAX_TELEMETRY_SCREENS]; // TODO EEPROM change should not be here anymore
540 uint8_t varioSource:7;
541 uint8_t varioCenterSilent:1;
542 int8_t varioCenterMax;
543 int8_t varioCenterMin;
544 int8_t varioMin;
545 int8_t varioMax;
547 #else
548 PACK(struct FrSkyChannelData {
549 uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
550 int16_t offset:12;
551 uint16_t type:4; // channel unit (0=volts, ...)
552 uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
553 uint8_t alarms_level:4;
554 uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>)
555 uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier
558 PACK(struct FrSkyTelemetryData {
559 FrSkyChannelData channels[MAX_FRSKY_A_CHANNELS];
560 uint8_t usrProto:2; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon
561 uint8_t blades:2; // How many blades for RPMs, 0=2 blades
562 uint8_t screensType:2;
563 uint8_t voltsSource:2;
564 int8_t varioMin:4;
565 int8_t varioMax:4;
566 FrSkyRSSIAlarm rssiAlarms[2];
567 FrSkyScreenData screens[MAX_TELEMETRY_SCREENS];
568 uint8_t varioSource:3;
569 int8_t varioCenterMin:5;
570 uint8_t currentSource:3;
571 int8_t varioCenterMax:5;
572 int8_t fasOffset;
574 #endif
577 * MAVLINK Telemetry structure
580 #if defined(TELEMETRY_MAVLINK)
581 PACK(struct MavlinkTelemetryData {
582 uint8_t rc_rssi_scale:4;
583 uint8_t pc_rssi_en:1;
584 uint8_t spare1:3;
585 uint8_t spare2[3];
587 #endif
590 * Telemetry Sensor structure
593 #if defined(CPUARM)
594 PACK(struct TelemetrySensor {
595 union {
596 uint16_t id; // data identifier, for FrSky we can reuse existing ones. Source unit is derived from type.
597 NOBACKUP(uint16_t persistentValue);
599 union {
600 uint8_t instance; // instance ID to allow handling multiple instances of same value type, for FrSky can be the physical ID of the sensor
601 NOBACKUP(uint8_t formula);
603 char label[TELEM_LABEL_LEN]; // user defined label
604 uint8_t type:1; // 0=custom / 1=calculated
605 uint8_t unit:5; // user can choose what unit to display each value in
606 uint8_t prec:2;
607 uint8_t autoOffset:1;
608 uint8_t filter:1;
609 uint8_t logs:1;
610 uint8_t persistent:1;
611 uint8_t onlyPositive:1;
612 uint8_t subId:3;
613 union {
614 NOBACKUP(PACK(struct {
615 uint16_t ratio;
616 int16_t offset;
617 }) custom);
618 NOBACKUP(PACK(struct {
619 uint8_t source;
620 uint8_t index;
621 uint16_t spare;
622 }) cell);
623 NOBACKUP(PACK(struct {
624 int8_t sources[4];
625 }) calc);
626 NOBACKUP(PACK(struct {
627 uint8_t source;
628 uint8_t spare[3];
629 }) consumption);
630 NOBACKUP(PACK(struct {
631 uint8_t gps;
632 uint8_t alt;
633 uint16_t spare;
634 }) dist);
635 uint32_t param;
637 NOBACKUP(
638 void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
639 void init(uint16_t id);
640 bool isAvailable() const;
641 int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
642 bool isConfigurable() const;
643 bool isPrecConfigurable() const;
644 int32_t getPrecMultiplier() const;
645 int32_t getPrecDivisor() const);
647 #endif
650 * Module structure
653 // Only used in case switch and if statements as "virtual" protocol
654 #define MM_RF_CUSTOM_SELECTED 0xff
655 PACK(struct ModuleData {
656 uint8_t type:4;
657 int8_t rfProtocol:4;
658 uint8_t channelsStart;
659 int8_t channelsCount; // 0=8 channels
660 uint8_t failsafeMode:4; // only 3 bits used
661 uint8_t subType:3;
662 uint8_t invertedSerial:1; // telemetry serial inverted from standard
663 int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
664 union {
665 struct {
666 int8_t delay:6;
667 uint8_t pulsePol:1;
668 uint8_t outputType:1; // false = open drain, true = push pull
669 int8_t frameLength;
670 } ppm;
671 NOBACKUP(struct {
672 uint8_t rfProtocolExtra:2;
673 uint8_t spare1:3;
674 uint8_t customProto:1;
675 uint8_t autoBindMode:1;
676 uint8_t lowPowerMode:1;
677 int8_t optionValue;
678 } multi);
679 NOBACKUP(struct {
680 uint8_t power:2; // 0=10 mW, 1=100 mW, 2=500 mW, 3=1W
681 uint8_t spare1:2;
682 uint8_t receiver_telem_off:1; // false = receiver telem enabled
683 uint8_t receiver_channel_9_16:1; // false = pwm out 1-8, true 9-16
684 uint8_t external_antenna:1; // false = internal antenna, true = external antenna
685 uint8_t fast:1; // TODO: to be used later by external module (fast means serial @ high speed)
686 uint8_t spare2;
687 } pxx);
688 NOBACKUP(struct {
689 uint8_t spare1:6;
690 uint8_t noninverted:1;
691 uint8_t spare2:1;
692 int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms)
693 } sbus);
696 // Helper functions to set both of the rfProto protocol at the same time
697 NOBACKUP(inline uint8_t getMultiProtocol(bool returnCustom) {
698 if (returnCustom && multi.customProto)
699 return MM_RF_CUSTOM_SELECTED;
700 return ((uint8_t) (rfProtocol & 0x0f)) + (multi.rfProtocolExtra << 4);
703 NOBACKUP(inline void setMultiProtocol(uint8_t proto)
705 rfProtocol = (uint8_t) (proto & 0x0f);
706 multi.rfProtocolExtra = (proto & 0x30) >> 4;
712 * Model structure
715 #if defined(CPUARM) || defined(CPUM2560)
716 typedef uint16_t BeepANACenter;
717 #else
718 typedef uint8_t BeepANACenter;
719 #endif
721 #if LEN_BITMAP_NAME > 0
722 #define MODEL_HEADER_BITMAP_FIELD NOBACKUP(char bitmap[LEN_BITMAP_NAME]);
723 #else
724 #define MODEL_HEADER_BITMAP_FIELD
725 #endif
728 PACK(struct ModelHeader {
729 char name[LEN_MODEL_NAME]; // must be first for eeLoadModelName
730 uint8_t modelId[NUM_MODULES];
731 MODEL_HEADER_BITMAP_FIELD
734 #if defined(COLORLCD)
735 typedef uint16_t swconfig_t;
736 typedef uint32_t swarnstate_t;
737 #elif defined(PCBX9E)
738 typedef uint64_t swconfig_t;
739 typedef uint64_t swarnstate_t;
740 typedef uint32_t swarnenable_t;
741 #elif defined(PCBTARANIS)
742 typedef uint16_t swconfig_t;
743 typedef uint16_t swarnstate_t;
744 typedef uint8_t swarnenable_t;
745 #else
746 typedef uint8_t swarnstate_t;
747 typedef uint8_t swarnenable_t;
748 #endif
750 #if defined(COLORLCD)
751 #define SWITCHES_WARNING_DATA \
752 NOBACKUP(swarnstate_t switchWarningState);
753 #else
754 #define SWITCHES_WARNING_DATA \
755 swarnstate_t switchWarningState; \
756 swarnenable_t switchWarningEnable;
757 #endif
759 #if defined(PCBSTD) && defined(GVARS)
760 #define MODEL_GVARS_DATA gvar_t gvars[MAX_GVARS];
761 #elif defined(PCBSTD)
762 #define MODEL_GVARS_DATA
763 #else
764 #define MODEL_GVARS_DATA GVarData gvars[MAX_GVARS];
765 #endif
767 #if defined(CPUARM)
768 #define TELEMETRY_DATA NOBACKUP(FrSkyTelemetryData frsky); NOBACKUP(RssiAlarmData rssiAlarms);
769 #elif defined(TELEMETRY_MAVLINK)
770 #define TELEMETRY_DATA MavlinkTelemetryData mavlink;
771 #elif defined(TELEMETRY_FRSKY) || !defined(PCBSTD)
772 #define TELEMETRY_DATA NOBACKUP(FrSkyTelemetryData frsky);
773 #else
774 #define TELEMETRY_DATA
775 #endif
777 #if defined(PCBHORUS)
778 #include "gui/480x272/layout.h"
779 #include "gui/480x272/topbar.h"
780 PACK(struct CustomScreenData {
781 char layoutName[10];
782 Layout::PersistentData layoutData;
784 #define CUSTOM_SCREENS_DATA \
785 NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]); \
786 NOBACKUP(Topbar::PersistentData topbarData); \
787 NOBACKUP(uint8_t view);
788 #elif defined(PCBTARANIS)
789 #define CUSTOM_SCREENS_DATA \
790 NOBACKUP(uint8_t view);
791 #else
792 #define CUSTOM_SCREENS_DATA
793 // TODO other boards could have their custom screens here as well
794 #endif
796 #if defined(PCBX12S)
797 #define MODELDATA_EXTRA NOBACKUP(uint8_t spare:3); NOBACKUP(uint8_t trainerMode:3); NOBACKUP(uint8_t potsWarnMode:2); ModuleData moduleData[NUM_MODULES+1]; NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); NOBACKUP(char inputNames[MAX_INPUTS][LEN_INPUT_NAME]); NOBACKUP(uint8_t potsWarnEnabled); NOBACKUP(int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]);
798 #elif defined(PCBX10)
799 #define MODELDATA_EXTRA NOBACKUP(uint8_t spare:3); NOBACKUP(uint8_t trainerMode:3); NOBACKUP(uint8_t potsWarnMode:2); ModuleData moduleData[NUM_MODULES+1]; NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); NOBACKUP(char inputNames[MAX_INPUTS][LEN_INPUT_NAME]); NOBACKUP(uint8_t potsWarnEnabled); NOBACKUP(int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]); NOBACKUP(uint8_t potsWarnSpares[NUM_DUMMY_ANAS]);
800 #elif defined(PCBTARANIS)
801 #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS];
802 #elif defined(PCBSKY9X)
803 #define MODELDATA_EXTRA uint8_t spare:6; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]; uint8_t rxBattAlarms[2];
804 #else
805 #define MODELDATA_EXTRA
806 #endif
808 PACK(struct ModelData {
809 ModelHeader header;
810 TimerData timers[MAX_TIMERS];
811 AVR_FIELD(uint8_t protocol:3)
812 ARM_FIELD(uint8_t telemetryProtocol:3)
813 uint8_t thrTrim:1; // Enable Throttle Trim
814 AVR_FIELD(int8_t ppmNCH:4)
815 ARM_FIELD(uint8_t noGlobalFunctions:1)
816 ARM_FIELD(uint8_t displayTrims:2)
817 ARM_FIELD(uint8_t ignoreSensorIds:1)
818 int8_t trimInc:3; // Trim Increments
819 uint8_t disableThrottleWarning:1;
820 ARM_FIELD(uint8_t displayChecklist:1)
821 AVR_FIELD(uint8_t pulsePol:1)
822 uint8_t extendedLimits:1;
823 uint8_t extendedTrims:1;
824 uint8_t throttleReversed:1;
825 AVR_FIELD(int8_t ppmDelay)
826 BeepANACenter beepANACenter;
827 MixData mixData[MAX_MIXERS];
828 LimitData limitData[MAX_OUTPUT_CHANNELS];
829 ExpoData expoData[MAX_EXPOS];
831 CurveData curves[MAX_CURVES];
832 int8_t points[MAX_CURVE_POINTS];
834 LogicalSwitchData logicalSw[MAX_LOGICAL_SWITCHES];
835 CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
836 SwashRingData swashR;
837 FlightModeData flightModeData[MAX_FLIGHT_MODES];
839 AVR_FIELD(int8_t ppmFrameLength) // 0=22.5ms (10ms-30ms) 0.5ms increments
841 NOBACKUP(uint8_t thrTraceSrc);
843 SWITCHES_WARNING_DATA
845 MODEL_GVARS_DATA
847 TELEMETRY_DATA
849 MODELDATA_EXTRA
851 ARM_FIELD(NOBACKUP(TelemetrySensor telemetrySensors[MAX_TELEMETRY_SENSORS]))
853 TARANIS_PCBX9E_FIELD(uint8_t toplcdTimer)
855 CUSTOM_SCREENS_DATA
860 * Radio structure
863 #if XPOTS_MULTIPOS_COUNT > 0
864 PACK(struct StepsCalibData {
865 uint8_t count;
866 uint8_t steps[XPOTS_MULTIPOS_COUNT-1];
868 #endif
870 PACK(struct CalibData {
871 int16_t mid;
872 int16_t spanNeg;
873 int16_t spanPos;
876 PACK(struct TrainerMix {
877 uint8_t srcChn:6; // 0-7 = ch1-8
878 uint8_t mode:2; // off,add-mode,subst-mode
879 int8_t studWeight;
882 PACK(struct TrainerData {
883 int16_t calib[4];
884 NOBACKUP(TrainerMix mix[4]);
887 #if defined(PCBHORUS)
888 #define SPLASH_MODE uint8_t splashSpares:3
889 #elif defined(FSPLASH)
890 #define SPLASH_MODE uint8_t splashMode:3
891 #elif defined(CPUARM)
892 #define SPLASH_MODE int8_t splashMode:3
893 #else
894 #define SPLASH_MODE uint8_t splashMode:1; uint8_t splashSpare:2
895 #endif
897 #if defined(CPUARM)
898 #define EXTRA_GENERAL_FIELDS_ARM \
899 NOBACKUP(uint8_t backlightBright); \
900 NOBACKUP(uint32_t globalTimer); \
901 NOBACKUP(uint8_t bluetoothBaudrate:4); \
902 NOBACKUP(uint8_t bluetoothMode:4); \
903 NOBACKUP(uint8_t countryCode); \
904 NOBACKUP(uint8_t imperial:1); \
905 NOBACKUP(uint8_t jitterFilter:1); /* 0 - active */\
906 uint8_t disableRssiPoweroffAlarm:1; \
907 NOBACKUP(uint8_t USBMode:2); \
908 NOBACKUP(uint8_t spareExtraArm:3); \
909 NOBACKUP(char ttsLanguage[2]); \
910 NOBACKUP(int8_t beepVolume:4); \
911 NOBACKUP(int8_t wavVolume:4); \
912 NOBACKUP(int8_t varioVolume:4); \
913 NOBACKUP(int8_t backgroundVolume:4); \
914 NOBACKUP(int8_t varioPitch); \
915 NOBACKUP(int8_t varioRange); \
916 NOBACKUP(int8_t varioRepeat); \
917 CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
918 #endif
920 #if defined(PCBHORUS)
921 #define EXTRA_GENERAL_FIELDS \
922 EXTRA_GENERAL_FIELDS_ARM \
923 NOBACKUP(uint8_t serial2Mode:4); \
924 uint8_t slidersConfig:4; \
925 uint32_t switchConfig; \
926 uint8_t potsConfig; /* two bits per pot */ \
927 NOBACKUP(char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]); \
928 NOBACKUP(char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_DUMMY_ANAS][LEN_ANA_NAME]); \
929 NOBACKUP(char currModelFilename[LEN_MODEL_FILENAME+1]); \
930 NOBACKUP(uint8_t spare:1); \
931 NOBACKUP(uint8_t blOffBright:7); \
932 NOBACKUP(char bluetoothName[LEN_BLUETOOTH_NAME]);
933 #elif defined(PCBTARANIS)
934 #if defined(BLUETOOTH)
935 #define BLUETOOTH_FIELDS \
936 uint8_t spare; \
937 char bluetoothName[LEN_BLUETOOTH_NAME];
938 #else
939 #define BLUETOOTH_FIELDS
940 #endif
941 #define EXTRA_GENERAL_FIELDS \
942 EXTRA_GENERAL_FIELDS_ARM \
943 uint8_t serial2Mode:4; \
944 uint8_t slidersConfig:4; \
945 uint8_t potsConfig; /* two bits per pot */\
946 uint8_t backlightColor; \
947 swarnstate_t switchUnlockStates; \
948 swconfig_t switchConfig; \
949 char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
950 char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME]; \
951 BLUETOOTH_FIELDS
952 #elif defined(PCBSKY9X)
953 #define EXTRA_GENERAL_FIELDS \
954 EXTRA_GENERAL_FIELDS_ARM \
955 int8_t txCurrentCalibration; \
956 int8_t temperatureWarn; \
957 uint8_t mAhWarn; \
958 uint16_t mAhUsed; \
959 int8_t temperatureCalib; \
960 uint8_t optrexDisplay; \
961 uint8_t sticksGain; \
962 uint8_t rotarySteps; \
963 char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
964 char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME];
965 #elif defined(CPUARM)
966 #define EXTRA_GENERAL_FIELDS EXTRA_GENERAL_FIELDS_ARM
967 #elif defined(PXX)
968 #define EXTRA_GENERAL_FIELDS uint8_t countryCode;
969 #else
970 #define EXTRA_GENERAL_FIELDS
971 #endif
973 #if defined(PCBHORUS)
974 #include "gui/480x272/theme.h"
975 #define THEME_DATA \
976 NOBACKUP(char themeName[8]); \
977 NOBACKUP(Theme::PersistentData themeData);
978 #else
979 #define THEME_DATA
980 #endif
982 #if defined(BUZZER)
983 #define BUZZER_FIELD NOBACKUP(int8_t buzzerMode:2); // -2=quiet, -1=only alarms, 0=no keys, 1=all (only used on AVR radios without audio hardware)
984 #else
985 #define BUZZER_FIELD NOBACKUP(int8_t spareRadio:2);
986 #endif
988 PACK(struct RadioData {
989 NOBACKUP(uint8_t version);
990 NOBACKUP(uint16_t variant);
991 CalibData calib[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS+NUM_DUMMY_ANAS];
992 NOBACKUP(uint16_t chkSum);
993 N_HORUS_FIELD(int8_t currModel);
994 N_HORUS_FIELD(uint8_t contrast);
995 NOBACKUP(uint8_t vBatWarn);
996 NOBACKUP(int8_t txVoltageCalibration);
997 NOBACKUP(int8_t backlightMode);
998 NOBACKUP(TrainerData trainer);
999 NOBACKUP(uint8_t view); // index of view in main screen
1000 BUZZER_FIELD
1001 NOBACKUP(uint8_t fai:1);
1002 NOBACKUP(int8_t beepMode:2); // -2=quiet, -1=only alarms, 0=no keys, 1=all
1003 NOBACKUP(uint8_t alarmsFlash:1);
1004 NOBACKUP(uint8_t disableMemoryWarning:1);
1005 NOBACKUP(uint8_t disableAlarmWarning:1);
1006 uint8_t stickMode:2;
1007 NOBACKUP(int8_t timezone:5);
1008 NOBACKUP(uint8_t adjustRTC:1);
1009 NOBACKUP(uint8_t inactivityTimer);
1010 AVR_FIELD(uint8_t mavbaud:3)
1011 ARM_FIELD(uint8_t telemetryBaudrate:3)
1012 SPLASH_MODE; /* 3bits */
1013 NOBACKUP(int8_t hapticMode:2); // -2=quiet, -1=only alarms, 0=no keys, 1=all
1014 AVR_FIELD(uint8_t blOffBright:4)
1015 AVR_FIELD(uint8_t blOnBright:4)
1016 ARM_FIELD(int8_t switchesDelay)
1017 NOBACKUP(uint8_t lightAutoOff);
1018 NOBACKUP(uint8_t templateSetup); // RETA order for receiver channels
1019 NOBACKUP(int8_t PPM_Multiplier);
1020 NOBACKUP(int8_t hapticLength);
1021 N_HORUS_FIELD(N_TARANIS_FIELD(N_PCBSTD_FIELD(uint8_t reNavigation)));
1022 N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t stickReverse));
1023 NOBACKUP(int8_t beepLength:3);
1024 NOBACKUP(int8_t hapticStrength:3);
1025 NOBACKUP(uint8_t gpsFormat:1);
1026 NOBACKUP(uint8_t unexpectedShutdown:1);
1027 NOBACKUP(uint8_t speakerPitch);
1028 NOBACKUP(int8_t speakerVolume);
1029 NOBACKUP(int8_t vBatMin);
1030 NOBACKUP(int8_t vBatMax);
1032 EXTRA_GENERAL_FIELDS
1034 THEME_DATA
1038 #undef SWITCHES_WARNING_DATA
1039 #undef MODEL_GVARS_DATA
1040 #undef TELEMETRY_DATA
1041 #undef MODELDATA_EXTRA
1042 #undef CUSTOM_SCREENS_DATA
1043 #undef SPLASH_MODE
1044 #undef EXTRA_GENERAL_FIELDS
1045 #undef THEME_DATA
1046 #undef NOBACKUP
1049 #if !defined(BACKUP)
1050 /* Compile time check to test structure size has not changed *
1051 Changing the size of one of the eeprom structs may cause wrong data to
1052 be loaded. Error out if the struct size changes.
1053 This function tries not avoid checking or using the defines
1054 other than the CPU arch and board type so changes in other
1055 defines also trigger the struct size changes */
1057 template <typename ToCheck, size_t expectedSize, size_t realSize = sizeof(ToCheck)>
1058 void check_size() {
1059 static_assert(expectedSize == realSize, "struct size changed");
1062 static inline void check_struct()
1064 #define CHKSIZE(x, y) check_size<struct x, y>()
1065 #define CHKTYPE(x, y) check_size<x, y>()
1067 #if defined(CPUARM)
1068 CHKSIZE(CurveRef, 2);
1069 #endif
1071 /* Difference between Taranis/Horus is LEN_EXPOMIX_NAME */
1072 /* LEN_FUNCTION_NAME is the difference in CustomFunctionData */
1074 #if defined(PCBX7) || defined(PCBXLITE)
1075 CHKSIZE(MixData, 20);
1076 CHKSIZE(ExpoData, 17);
1077 CHKSIZE(LimitData, 11);
1078 CHKSIZE(LogicalSwitchData, 9);
1079 CHKSIZE(CustomFunctionData, 11);
1080 CHKSIZE(FlightModeData, 28 + 2*NUM_TRIMS);
1081 CHKSIZE(TimerData, 11);
1082 CHKSIZE(SwashRingData, 8);
1083 CHKSIZE(FrSkyBarData, 6);
1084 CHKSIZE(FrSkyLineData, 4);
1085 CHKTYPE(union FrSkyScreenData, 24);
1086 CHKSIZE(FrSkyTelemetryData, 104);
1087 CHKSIZE(ModelHeader, 12);
1088 CHKSIZE(CurveData, 4);
1089 #elif defined(PCBTARANIS)
1090 CHKSIZE(MixData, 22);
1091 CHKSIZE(ExpoData, 19);
1092 CHKSIZE(LimitData, 13);
1093 CHKSIZE(LogicalSwitchData, 9);
1094 CHKSIZE(CustomFunctionData, 11);
1095 CHKSIZE(FlightModeData, 40);
1096 CHKSIZE(TimerData, 16);
1097 CHKSIZE(SwashRingData, 8);
1098 CHKSIZE(FrSkyBarData, 6);
1099 CHKSIZE(FrSkyLineData, 6);
1100 CHKTYPE(union FrSkyScreenData, 24);
1101 CHKSIZE(FrSkyTelemetryData, 104);
1102 CHKSIZE(ModelHeader, 24);
1103 CHKSIZE(CurveData, 4);
1104 #elif defined(PCBHORUS)
1105 CHKSIZE(MixData, 20);
1106 CHKSIZE(ExpoData, 17);
1107 CHKSIZE(LimitData, 13);
1108 CHKSIZE(CustomFunctionData, 9);
1109 CHKSIZE(FlightModeData, 44);
1110 CHKSIZE(TimerData, 16);
1111 CHKSIZE(SwashRingData, 8);
1112 CHKSIZE(FrSkyTelemetryData, 5);
1113 CHKSIZE(ModelHeader, 27);
1114 CHKSIZE(CurveData, 4);
1115 CHKSIZE(CustomScreenData, 610);
1116 CHKSIZE(Topbar::PersistentData, 216);
1117 #elif defined(PCBSKY9X)
1118 CHKSIZE(MixData, 20);
1119 CHKSIZE(ExpoData, 17);
1120 CHKSIZE(LimitData, 11);
1121 CHKSIZE(CustomFunctionData, 9);
1122 CHKSIZE(FlightModeData, 38);
1123 CHKSIZE(TimerData, 11);
1124 CHKSIZE(SwashRingData, 8);
1125 CHKSIZE(FrSkyBarData, 5);
1126 CHKSIZE(FrSkyLineData, 2);
1127 CHKSIZE(FrSkyTelemetryData, 88);
1128 CHKSIZE(ModelHeader, 12);
1129 CHKTYPE(CurveData, 4);
1130 #else
1131 // Common for all variants
1132 CHKSIZE(LimitData, 5);
1133 CHKSIZE(SwashRingData, 3);
1134 CHKSIZE(FrSkyBarData, 3);
1135 CHKSIZE(FrSkyLineData, 2);
1136 CHKSIZE(FrSkyTelemetryData, 43);
1137 CHKSIZE(ModelHeader, 11);
1138 CHKTYPE(CurveData, 1);
1140 // AVR
1141 #if defined(CPUM2560) || defined(CPUM2561)
1142 CHKSIZE(ExpoData, 5);
1143 CHKSIZE(MixData, 10);
1144 #else
1145 CHKSIZE(MixData, 9);
1146 CHKSIZE(ExpoData, 4);
1147 #endif
1149 #if defined(CPUM2560)
1150 CHKSIZE(CustomFunctionData, 4);
1151 CHKSIZE(TimerData, 6);
1152 #else
1153 CHKSIZE(CustomFunctionData, 3);
1154 CHKSIZE(TimerData, 3);
1155 #endif
1157 #if defined(PCBSTD)
1158 CHKSIZE(FlightModeData, 13);
1159 CHKSIZE(RadioData, 84);
1160 #else
1161 CHKSIZE(FlightModeData, 30);
1162 CHKSIZE(RadioData, 85);
1163 #endif
1165 #endif /* board specific ifdefs*/
1167 #if defined(CPUARM)
1168 CHKSIZE(LogicalSwitchData, 9);
1169 CHKSIZE(TelemetrySensor, 13);
1170 CHKSIZE(ModuleData,70);
1171 #else
1172 CHKSIZE(LogicalSwitchData, 3);
1173 CHKSIZE(FrSkyChannelData, 6);
1174 CHKSIZE(ModuleData, 38);
1175 #endif
1177 #if !defined(PCBSTD)
1178 CHKSIZE(GVarData, 7);
1179 #endif
1181 #if defined(CPUARM)
1182 CHKSIZE(RssiAlarmData, 2);
1183 #else
1184 CHKSIZE(FrSkyRSSIAlarm, 1);
1185 #endif
1186 CHKSIZE(TrainerData, 16);
1188 #if defined(PCBXLITE)
1189 CHKSIZE(RadioData, 844);
1190 CHKSIZE(ModelData, 6025);
1191 #elif defined(PCBX7)
1192 CHKSIZE(RadioData, 850);
1193 CHKSIZE(ModelData, 6025);
1194 #elif defined(PCBX9E)
1195 CHKSIZE(RadioData, 952);
1196 CHKSIZE(ModelData, 6520);
1197 #elif defined(PCBX9D)
1198 CHKSIZE(RadioData, 872);
1199 CHKSIZE(ModelData, 6507);
1200 #elif defined(PCBSKY9X)
1201 CHKSIZE(RadioData, 727);
1202 CHKSIZE(ModelData, 5188);
1203 #elif defined(PCBHORUS)
1204 CHKSIZE(RadioData, 847);
1205 CHKSIZE(ModelData, 9380);
1206 #endif
1208 #undef CHKSIZE
1209 #undef CHKSIZEUNION
1211 #endif /* BACKUP */