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