1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-12 19:10:19 +03:00
opentx/radio/src/datastructs.h
2022-09-01 16:42:35 +08:00

1209 lines
31 KiB
C++

/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
// No include guards here, this file may be included many times in different namespaces
// i.e. BACKUP RAM Backup/Restore functions
#include <inttypes.h>
#include "dataconstants.h"
#if defined(CPUARM)
#define ARM_FIELD(x) x;
#define AVR_FIELD(x)
#else
#define ARM_FIELD(x)
#define AVR_FIELD(x) x;
#endif
#if defined(PCBSTD)
#define N_PCBSTD_FIELD(x)
#else
#define N_PCBSTD_FIELD(x) x;
#endif
#if defined(PCBTARANIS)
#define N_TARANIS_FIELD(x)
#define TARANIS_FIELD(x) x;
#else
#define N_TARANIS_FIELD(x) x;
#define TARANIS_FIELD(x)
#endif
#if defined(PCBX9E)
#define TARANIS_PCBX9E_FIELD(x) x;
#else
#define TARANIS_PCBX9E_FIELD(x)
#endif
#if defined(PCBHORUS)
#define N_HORUS_FIELD(x)
#define HORUS_FIELD(x) x;
#else
#define N_HORUS_FIELD(x) x;
#define HORUS_FIELD(x)
#endif
#if defined(BACKUP)
#define NOBACKUP(...)
#else
#define NOBACKUP(...) __VA_ARGS__
#endif
#if defined(PCBTARANIS) || defined(PCBHORUS)
typedef uint16_t source_t;
#else
typedef uint8_t source_t;
#endif
/*
* Mixer structure
*/
#if defined(CPUARM)
PACK(struct CurveRef {
uint8_t type;
int8_t value;
});
PACK(struct MixData {
int16_t weight:11; // GV1=-1024, -GV1=1023
uint16_t destCh:5;
uint16_t srcRaw:10; // srcRaw=0 means not used
uint16_t carryTrim:1;
uint16_t mixWarn:2; // mixer warning
uint16_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
uint16_t spare:1;
int32_t offset:14;
int32_t swtch:9;
uint32_t flightModes:9;
CurveRef curve;
uint8_t delayUp;
uint8_t delayDown;
uint8_t speedUp;
uint8_t speedDown;
NOBACKUP(char name[LEN_EXPOMIX_NAME]);
});
#elif defined(CPUM2560) || defined(CPUM2561)
PACK(struct MixData {
uint8_t destCh:4; // 0, 1..MAX_OUTPUT_CHANNELS
uint8_t curveMode:1; // O=curve, 1=differential
uint8_t noExpo:1;
uint8_t weightMode:1;
uint8_t offsetMode:1;
uint8_t srcRaw;
int8_t weight;
int8_t swtch;
uint8_t flightModes;
uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
int8_t carryTrim:3;
uint8_t mixWarn:2; // mixer warning
uint8_t spare:1;
uint8_t delayUp:4;
uint8_t delayDown:4;
uint8_t speedUp:4;
uint8_t speedDown:4;
int8_t curveParam;
int8_t offset;
});
#else
PACK(struct MixData {
uint8_t destCh:4; // 0, 1..MAX_OUTPUT_CHANNELS
uint8_t curveMode:1; // O=curve, 1=differential
uint8_t noExpo:1;
uint8_t weightMode:1;
uint8_t offsetMode:1;
int8_t weight;
int8_t swtch:6;
uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
uint8_t flightModes:5;
int8_t carryTrim:3;
uint8_t srcRaw:6;
uint8_t mixWarn:2; // mixer warning
uint8_t delayUp:4;
uint8_t delayDown:4;
uint8_t speedUp:4;
uint8_t speedDown:4;
int8_t curveParam;
int8_t offset;
});
#endif
/*
* Expo/Input structure
*/
#if defined(CPUARM)
PACK(struct ExpoData {
uint16_t mode:2;
uint16_t scale:14;
uint16_t srcRaw:10;
int16_t carryTrim:6;
uint32_t chn:5;
int32_t swtch:9;
uint32_t flightModes:9;
int32_t weight:8;
int32_t spare:1;
NOBACKUP(char name[LEN_EXPOMIX_NAME]);
int8_t offset;
CurveRef curve;
});
#elif defined(CPUM2560) || defined(CPUM2561)
PACK(struct ExpoData {
uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
uint8_t chn:2;
uint8_t curveMode:1;
uint8_t spare:3;
uint8_t flightModes;
int8_t swtch;
uint8_t weight;
int8_t curveParam;
});
#else
PACK(struct ExpoData {
uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
int8_t swtch:6;
uint8_t chn:2;
uint8_t flightModes:5;
uint8_t curveMode:1;
uint8_t weight; // One spare bit here (used for GVARS)
int8_t curveParam;
});
#endif
/*
* Limit structure
*/
#if defined(CPUARM)
PACK(struct LimitData {
int32_t min:11;
int32_t max:11;
int32_t ppmCenter:10;
int16_t offset:11;
uint16_t symetrical:1;
uint16_t revert:1;
uint16_t spare:3;
int8_t curve;
NOBACKUP(char name[LEN_CHANNEL_NAME]);
});
#else
PACK(struct LimitData {
int8_t min;
int8_t max;
int8_t ppmCenter;
int16_t offset:14;
uint16_t symetrical:1;
uint16_t revert:1;
});
#endif
/*
* LogicalSwitch structure
*/
#if defined(CPUARM)
PACK(struct LogicalSwitchData {
uint8_t func;
int32_t v1:10;
int32_t v3:10;
int32_t andsw:9; // TODO rename to xswtch
uint32_t andswtype:1; // TODO rename to xswtchType (AND / OR)
uint32_t spare:2; // anything else needed?
int16_t v2;
uint8_t delay;
uint8_t duration;
});
#else
PACK(struct LogicalSwitchData {
int8_t v1; //input
int8_t v2; //offset
uint8_t func:4;
uint8_t andsw:4;
});
#endif
/*
* SpecialFunction structure
*/
#if defined(CPUARM)
#if defined(PCBTARANIS)
#define CFN_SPARE_TYPE int32_t
#else
#define CFN_SPARE_TYPE int16_t
#endif
PACK(struct CustomFunctionData {
int16_t swtch:9;
uint16_t func:7;
PACK(union {
NOBACKUP(PACK(struct {
char name[LEN_FUNCTION_NAME];
}) play);
PACK(struct {
int16_t val;
uint8_t mode;
uint8_t param;
NOBACKUP(CFN_SPARE_TYPE spare);
}) all;
PACK(struct {
int32_t val1;
NOBACKUP(CFN_SPARE_TYPE val2);
}) clear;
});
uint8_t active;
});
#elif defined(CPUM2560)
PACK(struct CustomFunctionData {
int8_t swtch;
uint8_t func;
uint8_t mode:2;
uint8_t param:4;
uint8_t active:1;
uint8_t spare:1;
uint8_t value;
});
#else
PACK(struct CustomFunctionData {
PACK(union {
PACK(struct {
int16_t swtch:6;
uint16_t func:4;
uint16_t mode:2;
uint16_t param:3;
uint16_t active:1;
}) gvar;
PACK(struct {
int16_t swtch:6;
uint16_t func:4;
uint16_t param:4;
uint16_t spare:1;
uint16_t active:1;
}) all;
});
uint8_t value;
});
#endif
/*
* FlightMode structure
*/
#if defined(CPUARM)
PACK(struct trim_t {
int16_t value:11;
uint16_t mode:5;
});
#else
typedef int16_t trim_t;
#endif
typedef int16_t gvar_t;
#if MAX_ROTARY_ENCODERS > 0
#define FLIGHT_MODE_ROTARY_ENCODERS_FIELD int16_t rotaryEncoders[MAX_ROTARY_ENCODERS];
#else
#define FLIGHT_MODE_ROTARY_ENCODERS_FIELD
#endif
#if defined(CPUARM)
PACK(struct FlightModeData {
trim_t trim[NUM_TRIMS];
NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
int16_t swtch:9; // swtch of phase[0] is not used
int16_t spare:7;
uint8_t fadeIn;
uint8_t fadeOut;
FLIGHT_MODE_ROTARY_ENCODERS_FIELD
gvar_t gvars[MAX_GVARS];
});
#elif !defined(PCBSTD)
PACK(struct FlightModeData {
trim_t trim[NUM_STICKS];
int8_t swtch; // swtch of phase[0] is not used
NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
uint8_t fadeIn:4;
uint8_t fadeOut:4;
FLIGHT_MODE_ROTARY_ENCODERS_FIELD
gvar_t gvars[MAX_GVARS];
});
#else
PACK(struct FlightModeData {
int8_t trim[NUM_STICKS];
int8_t trim_ext; // 2 extra bits per trim (10bits)
int8_t swtch; // swtch of phase[0] is not used
NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
uint8_t fadeIn:4;
uint8_t fadeOut:4;
});
#endif
/*
* Curve structure
*/
#if defined(CPUARM)
PACK(struct CurveData {
uint8_t type:1;
uint8_t smooth:1;
int8_t points:6; // TODO conversion
NOBACKUP(char name[LEN_CURVE_NAME]);
});
#else
typedef int8_t CurveData;
#endif
/*
* GVar structure
*/
#if !defined(PCBSTD)
PACK(struct GVarData {
NOBACKUP(char name[LEN_GVAR_NAME]);
uint32_t min:12;
uint32_t max:12;
uint32_t popup:1;
uint32_t prec:1;
uint32_t unit:2;
uint32_t spare:4;
});
#endif
/*
* Timer structure
*/
#if defined(CPUARM)
PACK(struct TimerData {
int32_t mode:9; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint32_t start:23;
int32_t value:24;
uint32_t countdownBeep:2;
uint32_t minuteBeep:1;
uint32_t persistent:2;
int32_t countdownStart:2;
uint32_t direction:1;
NOBACKUP(char name[LEN_TIMER_NAME]);
});
#elif defined(CPUM2560)
PACK(struct TimerData {
int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint16_t start;
uint8_t countdownBeep:2;
uint8_t minuteBeep:1;
uint8_t persistent:2;
uint8_t countdownStart:3;
uint16_t value;
});
#else
PACK(struct TimerData {
int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint16_t start:12;
uint16_t countdownBeep:1;
uint16_t minuteBeep:1;
uint16_t spare:2;
});
#endif
/*
* Swash Ring structure
*/
#if defined(VIRTUAL_INPUTS)
PACK(struct SwashRingData {
uint8_t type;
uint8_t value;
uint8_t collectiveSource;
uint8_t aileronSource;
uint8_t elevatorSource;
int8_t collectiveWeight;
int8_t aileronWeight;
int8_t elevatorWeight;
});
#else
PACK(struct SwashRingData {
uint8_t invertELE:1;
uint8_t invertAIL:1;
uint8_t invertCOL:1;
uint8_t type:5;
uint8_t collectiveSource;
uint8_t value;
});
#endif
#if MAX_SCRIPTS > 0
union ScriptDataInput {
int16_t value;
source_t source;
};
PACK(struct ScriptData {
char file[LEN_SCRIPT_FILENAME];
char name[LEN_SCRIPT_NAME];
ScriptDataInput inputs[MAX_SCRIPT_INPUTS];
});
#endif
/*
* Frsky Telemetry structure
*/
PACK(struct FrSkyRSSIAlarm {
int8_t level:2;
int8_t value:6;
});
#if defined(CPUARM)
typedef int16_t ls_telemetry_value_t;
#else
typedef uint8_t ls_telemetry_value_t;
#endif
#if !defined(COLORLCD)
PACK(struct FrSkyBarData {
source_t source;
ls_telemetry_value_t barMin; // minimum for bar display
ls_telemetry_value_t barMax; // ditto for max display (would usually = ratio)
});
PACK(struct FrSkyLineData {
source_t sources[NUM_LINE_ITEMS];
});
#if defined(PCBTARANIS)
PACK(struct TelemetryScriptData {
char file[LEN_SCRIPT_FILENAME];
int16_t inputs[MAX_TELEM_SCRIPT_INPUTS];
});
#endif
union FrSkyScreenData {
FrSkyBarData bars[4];
FrSkyLineData lines[4];
#if defined(PCBTARANIS)
TelemetryScriptData script;
#endif
};
#endif
#if defined(COLORLCD)
PACK(struct FrSkyTelemetryData {
uint8_t varioSource:7;
uint8_t varioCenterSilent:1;
int8_t varioCenterMax;
int8_t varioCenterMin;
int8_t varioMin;
int8_t varioMax;
FrSkyRSSIAlarm rssiAlarms[2];
});
#elif defined(CPUARM)
PACK(struct FrSkyChannelData {
uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
int16_t offset:12;
uint16_t type:4; // channel unit (0=volts, ...)
uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
uint8_t alarms_level:4;
uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>)
uint8_t spare:2;
uint8_t multiplier; // 0=no multiplier, 1=*2 multiplier
});
// TODO remove this also on Taranis
PACK(struct FrSkyTelemetryData {
uint8_t voltsSource;
uint8_t altitudeSource;
uint8_t screensType; // 2bits per screen (None/Gauges/Numbers/Script)
FrSkyScreenData screens[MAX_TELEMETRY_SCREENS]; // TODO EEPROM change should not be here anymore
uint8_t varioSource:7;
uint8_t varioCenterSilent:1;
int8_t varioCenterMax;
int8_t varioCenterMin;
int8_t varioMin;
int8_t varioMax;
FrSkyRSSIAlarm rssiAlarms[2];
});
#else
PACK(struct FrSkyChannelData {
uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
int16_t offset:12;
uint16_t type:4; // channel unit (0=volts, ...)
uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
uint8_t alarms_level:4;
uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>)
uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier
});
PACK(struct FrSkyTelemetryData {
FrSkyChannelData channels[MAX_FRSKY_A_CHANNELS];
uint8_t usrProto:2; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon
uint8_t blades:2; // How many blades for RPMs, 0=2 blades
uint8_t screensType:2;
uint8_t voltsSource:2;
int8_t varioMin:4;
int8_t varioMax:4;
FrSkyRSSIAlarm rssiAlarms[2];
FrSkyScreenData screens[MAX_TELEMETRY_SCREENS];
uint8_t varioSource:3;
int8_t varioCenterMin:5;
uint8_t currentSource:3;
int8_t varioCenterMax:5;
int8_t fasOffset;
});
#endif
/*
* MAVLINK Telemetry structure
*/
#if defined(TELEMETRY_MAVLINK)
PACK(struct MavlinkTelemetryData {
uint8_t rc_rssi_scale:4;
uint8_t pc_rssi_en:1;
uint8_t spare1:3;
uint8_t spare2[3];
});
#endif
/*
* Telemetry Sensor structure
*/
#if defined(CPUARM)
PACK(struct TelemetrySensor {
union {
uint16_t id; // data identifier, for FrSky we can reuse existing ones. Source unit is derived from type.
uint16_t persistentValue;
};
union {
uint8_t instance; // instance ID to allow handling multiple instances of same value type, for FrSky can be the physical ID of the sensor
uint8_t formula;
};
char label[TELEM_LABEL_LEN]; // user defined label
uint8_t type:1; // 0=custom / 1=calculated
uint8_t unit:5; // user can choose what unit to display each value in
uint8_t prec:2;
uint8_t autoOffset:1;
uint8_t filter:1;
uint8_t logs:1;
uint8_t persistent:1;
uint8_t onlyPositive:1;
uint8_t subId:3;
union {
PACK(struct {
uint16_t ratio;
int16_t offset;
}) custom;
PACK(struct {
uint8_t source;
uint8_t index;
uint16_t spare;
}) cell;
PACK(struct {
int8_t sources[4];
}) calc;
PACK(struct {
uint8_t source;
uint8_t spare[3];
}) consumption;
PACK(struct {
uint8_t gps;
uint8_t alt;
uint16_t spare;
}) dist;
uint32_t param;
};
NOBACKUP(
void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
void init(uint16_t id);
bool isAvailable() const;
int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
bool isConfigurable() const;
bool isPrecConfigurable() const;
int32_t getPrecMultiplier() const;
int32_t getPrecDivisor() const);
});
#endif
/*
* Module structure
*/
// Only used in case switch and if statements as "virtual" protocol
#define MM_RF_CUSTOM_SELECTED 0xff
PACK(struct ModuleData {
uint8_t type:4;
int8_t rfProtocol:4;
uint8_t channelsStart;
int8_t channelsCount; // 0=8 channels
uint8_t failsafeMode:4; //only 3 bits used
uint8_t subType:3;
uint8_t invertedSerial:1; // telemetry serial inverted from standard
int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
union {
struct {
int8_t delay:6;
uint8_t pulsePol:1;
uint8_t outputType:1; // false = open drain, true = push pull
int8_t frameLength;
} ppm;
NOBACKUP(struct {
uint8_t rfProtocolExtra:2;
uint8_t spare:3;
uint8_t customProto:1;
uint8_t autoBindMode:1;
uint8_t lowPowerMode:1;
int8_t optionValue;
} multi);
NOBACKUP(struct {
uint8_t spare:4;
uint8_t receiver_telem_off:1; // false = receiver telem enabled
uint8_t receiver_channel_9_16:1; // false = pwm out 1-8, true 9-16
uint8_t external_antenna:1; // false = internal antenna, true = external antenna
uint8_t spare2:1;
uint8_t spare3;
} pxx);
};
// Helper functions to set both of the rfProto protocol at the same time
NOBACKUP(inline uint8_t getMultiProtocol(bool returnCustom) {
if (returnCustom && multi.customProto)
return MM_RF_CUSTOM_SELECTED;
return ((uint8_t) (rfProtocol & 0x0f)) + (multi.rfProtocolExtra << 4);
})
NOBACKUP(inline void setMultiProtocol(uint8_t proto)
{
rfProtocol = (uint8_t) (proto & 0x0f);
multi.rfProtocolExtra = (proto & 0x30) >> 4;
})
});
/*
* Model structure
*/
#if defined(CPUARM) || defined(CPUM2560)
typedef uint16_t BeepANACenter;
#else
typedef uint8_t BeepANACenter;
#endif
#if LEN_BITMAP_NAME > 0
#define MODEL_HEADER_BITMAP_FIELD NOBACKUP(char bitmap[LEN_BITMAP_NAME]);
#else
#define MODEL_HEADER_BITMAP_FIELD
#endif
PACK(struct ModelHeader {
char name[LEN_MODEL_NAME]; // must be first for eeLoadModelName
uint8_t modelId[NUM_MODULES];
MODEL_HEADER_BITMAP_FIELD
});
#if defined(COLORLCD)
typedef uint16_t swconfig_t;
typedef uint32_t swarnstate_t;
#elif defined(PCBX9E)
typedef uint64_t swconfig_t;
typedef uint64_t swarnstate_t;
typedef uint32_t swarnenable_t;
#elif defined(PCBTARANIS)
typedef uint16_t swconfig_t;
typedef uint16_t swarnstate_t;
typedef uint8_t swarnenable_t;
#else
typedef uint8_t swarnstate_t;
typedef uint8_t swarnenable_t;
#endif
#if defined(COLORLCD)
#define SWITCHES_WARNING_DATA \
NOBACKUP(swarnstate_t switchWarningState);
#else
#define SWITCHES_WARNING_DATA \
swarnstate_t switchWarningState; \
swarnenable_t switchWarningEnable;
#endif
#if defined(PCBSTD) && defined(GVARS)
#define MODEL_GVARS_DATA gvar_t gvars[MAX_GVARS];
#elif defined(PCBSTD)
#define MODEL_GVARS_DATA
#else
#define MODEL_GVARS_DATA GVarData gvars[MAX_GVARS];
#endif
#if defined(TELEMETRY_MAVLINK)
#define TELEMETRY_DATA MavlinkTelemetryData mavlink;
#elif defined(TELEMETRY_FRSKY) || !defined(PCBSTD)
#define TELEMETRY_DATA NOBACKUP(FrSkyTelemetryData frsky);
#else
#define TELEMETRY_DATA
#endif
#if defined(PCBHORUS)
#include "gui/480x272/layout.h"
#include "gui/480x272/topbar.h"
PACK(struct CustomScreenData {
char layoutName[10];
Layout::PersistentData layoutData;
});
#define CUSTOM_SCREENS_DATA \
NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]); \
NOBACKUP(Topbar::PersistentData topbarData); \
NOBACKUP(uint8_t view);
#elif defined(PCBTARANIS)
#define CUSTOM_SCREENS_DATA \
NOBACKUP(uint8_t view);
#else
#define CUSTOM_SCREENS_DATA
// TODO other boards could have their custom screens here as well
#endif
#if defined(PCBX12S)
#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]);
#elif defined(PCBX10)
#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]);
#elif defined(PCBFLAMENCO)
#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];
#elif defined(PCBTARANIS)
#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];
#elif defined(PCBSKY9X)
#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];
#else
#define MODELDATA_EXTRA
#endif
PACK(struct ModelData {
ModelHeader header;
TimerData timers[MAX_TIMERS];
AVR_FIELD(uint8_t protocol:3)
ARM_FIELD(uint8_t telemetryProtocol:3)
uint8_t thrTrim:1; // Enable Throttle Trim
AVR_FIELD(int8_t ppmNCH:4)
ARM_FIELD(uint8_t noGlobalFunctions:1)
ARM_FIELD(uint8_t displayTrims:2)
ARM_FIELD(uint8_t ignoreSensorIds:1)
int8_t trimInc:3; // Trim Increments
uint8_t disableThrottleWarning:1;
ARM_FIELD(uint8_t displayChecklist:1)
AVR_FIELD(uint8_t pulsePol:1)
uint8_t extendedLimits:1;
uint8_t extendedTrims:1;
uint8_t throttleReversed:1;
AVR_FIELD(int8_t ppmDelay)
BeepANACenter beepANACenter;
MixData mixData[MAX_MIXERS];
LimitData limitData[MAX_OUTPUT_CHANNELS];
ExpoData expoData[MAX_EXPOS];
CurveData curves[MAX_CURVES];
int8_t points[MAX_CURVE_POINTS];
LogicalSwitchData logicalSw[MAX_LOGICAL_SWITCHES];
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
SwashRingData swashR;
FlightModeData flightModeData[MAX_FLIGHT_MODES];
uint8_t xValue[2];
AVR_FIELD(int8_t ppmFrameLength) // 0=22.5ms (10ms-30ms) 0.5ms increments
NOBACKUP(uint8_t thrTraceSrc);
SWITCHES_WARNING_DATA
MODEL_GVARS_DATA
TELEMETRY_DATA
MODELDATA_EXTRA
ARM_FIELD(NOBACKUP(TelemetrySensor telemetrySensors[MAX_TELEMETRY_SENSORS]))
TARANIS_PCBX9E_FIELD(uint8_t toplcdTimer)
CUSTOM_SCREENS_DATA
});
/*
* Radio structure
*/
#if XPOTS_MULTIPOS_COUNT > 0
PACK(struct StepsCalibData {
uint8_t count;
uint8_t steps[XPOTS_MULTIPOS_COUNT-1];
});
#endif
PACK(struct CalibData {
int16_t mid;
int16_t spanNeg;
int16_t spanPos;
});
PACK(struct TrainerMix {
uint8_t srcChn:6; // 0-7 = ch1-8
uint8_t mode:2; // off,add-mode,subst-mode
int8_t studWeight;
});
PACK(struct TrainerData {
int16_t calib[4];
NOBACKUP(TrainerMix mix[4]);
});
#if defined(PCBHORUS)
#define SPLASH_MODE uint8_t splashSpares:3
#elif defined(FSPLASH)
#define SPLASH_MODE uint8_t splashMode:3
#elif defined(PCBTARANIS)
#define SPLASH_MODE int8_t splashMode:3
#else
#define SPLASH_MODE uint8_t splashMode:1; uint8_t splashSpare:2
#endif
#if defined(CPUARM)
#define EXTRA_GENERAL_FIELDS_ARM \
NOBACKUP(uint8_t backlightBright); \
NOBACKUP(uint32_t globalTimer); \
NOBACKUP(uint8_t btBaudrate); \
NOBACKUP(uint8_t countryCode); \
NOBACKUP(uint8_t imperial:1); \
NOBACKUP(uint8_t jitterFilter:1); /* 0 - active */\
NOBACKUP(uint8_t spareExtraArm:6); \
NOBACKUP(char ttsLanguage[2]); \
NOBACKUP(int8_t beepVolume:4); \
NOBACKUP(int8_t wavVolume:4); \
NOBACKUP(int8_t varioVolume:4); \
NOBACKUP(int8_t backgroundVolume:4); \
NOBACKUP(int8_t varioPitch); \
NOBACKUP(int8_t varioRange); \
NOBACKUP(int8_t varioRepeat); \
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
#endif
#if defined(PCBHORUS)
#define EXTRA_GENERAL_FIELDS \
EXTRA_GENERAL_FIELDS_ARM \
NOBACKUP(uint8_t serial2Mode:4); \
uint8_t slidersConfig:4; \
uint32_t switchConfig; \
uint8_t potsConfig; /* two bits per pot */ \
NOBACKUP(char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]); \
NOBACKUP(char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_DUMMY_ANAS][LEN_ANA_NAME]); \
NOBACKUP(char currModelFilename[LEN_MODEL_FILENAME+1]); \
NOBACKUP(uint8_t bluetoothEnable:1); \
NOBACKUP(uint8_t blOffBright:7); \
NOBACKUP(char bluetoothName[LEN_BLUETOOTH_NAME]);
#elif defined(PCBFLAMENCO)
#define EXTRA_GENERAL_FIELDS \
EXTRA_GENERAL_FIELDS_ARM \
uint8_t serial2Mode:4; \
uint8_t spareExtra:4; \
uint32_t switchConfig; \
uint8_t potsType; /*two bits for every pot*/\
char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME];
#elif defined(PCBTARANIS)
#if defined(PCBX9E) || defined(PCBX7)
#define BLUETOOTH_FIELDS \
uint8_t bluetoothEnable; \
char bluetoothName[LEN_BLUETOOTH_NAME];
#else
#define BLUETOOTH_FIELDS
#endif
#define EXTRA_GENERAL_FIELDS \
EXTRA_GENERAL_FIELDS_ARM \
uint8_t serial2Mode:4; \
uint8_t slidersConfig:4; \
uint8_t potsConfig; /* two bits per pot */\
uint8_t backlightColor; \
swarnstate_t switchUnlockStates; \
swconfig_t switchConfig; \
char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME]; \
BLUETOOTH_FIELDS
#elif defined(PCBSKY9X)
#define EXTRA_GENERAL_FIELDS \
EXTRA_GENERAL_FIELDS_ARM \
int8_t txCurrentCalibration; \
int8_t temperatureWarn; \
uint8_t mAhWarn; \
uint16_t mAhUsed; \
int8_t temperatureCalib; \
uint8_t optrexDisplay; \
uint8_t sticksGain; \
uint8_t rotarySteps; \
char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME];
#elif defined(CPUARM)
#define EXTRA_GENERAL_FIELDS EXTRA_GENERAL_FIELDS_ARM
#elif defined(PXX)
#define EXTRA_GENERAL_FIELDS uint8_t countryCode;
#else
#define EXTRA_GENERAL_FIELDS
#endif
#if defined(PCBHORUS)
#include "gui/480x272/theme.h"
#define THEME_DATA \
NOBACKUP(char themeName[8]); \
NOBACKUP(Theme::PersistentData themeData);
#else
#define THEME_DATA
#endif
#if defined(BUZZER)
#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)
#else
#define BUZZER_FIELD NOBACKUP(int8_t spareRadio:2);
#endif
PACK(struct RadioData {
NOBACKUP(uint8_t version);
NOBACKUP(uint16_t variant);
CalibData calib[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS+NUM_DUMMY_ANAS];
NOBACKUP(uint16_t chkSum);
N_HORUS_FIELD(int8_t currModel);
N_HORUS_FIELD(uint8_t contrast);
NOBACKUP(uint8_t vBatWarn);
NOBACKUP(int8_t txVoltageCalibration);
NOBACKUP(int8_t backlightMode);
NOBACKUP(TrainerData trainer);
NOBACKUP(uint8_t view); // index of view in main screen
BUZZER_FIELD
NOBACKUP(uint8_t fai:1);
NOBACKUP(int8_t beepMode:2); // -2=quiet, -1=only alarms, 0=no keys, 1=all
NOBACKUP(uint8_t alarmsFlash:1);
NOBACKUP(uint8_t disableMemoryWarning:1);
NOBACKUP(uint8_t disableAlarmWarning:1);
uint8_t stickMode:2;
NOBACKUP(int8_t timezone:5);
NOBACKUP(uint8_t adjustRTC:1);
NOBACKUP(uint8_t inactivityTimer);
NOBACKUP(uint8_t mavbaud:3);
SPLASH_MODE; /* 3bits */
NOBACKUP(int8_t hapticMode:2); // -2=quiet, -1=only alarms, 0=no keys, 1=all
AVR_FIELD(uint8_t blOffBright:4)
AVR_FIELD(uint8_t blOnBright:4)
ARM_FIELD(int8_t switchesDelay)
NOBACKUP(uint8_t lightAutoOff);
NOBACKUP(uint8_t templateSetup); // RETA order for receiver channels
NOBACKUP(int8_t PPM_Multiplier);
NOBACKUP(int8_t hapticLength);
N_HORUS_FIELD(N_TARANIS_FIELD(N_PCBSTD_FIELD(uint8_t reNavigation)));
N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t stickReverse));
NOBACKUP(int8_t beepLength:3);
NOBACKUP(int8_t hapticStrength:3);
NOBACKUP(uint8_t gpsFormat:1);
NOBACKUP(uint8_t unexpectedShutdown:1);
NOBACKUP(uint8_t speakerPitch);
NOBACKUP(int8_t speakerVolume);
NOBACKUP(int8_t vBatMin);
NOBACKUP(int8_t vBatMax);
EXTRA_GENERAL_FIELDS
THEME_DATA
});
#undef SWITCHES_WARNING_DATA
#undef MODEL_GVARS_DATA
#undef TELEMETRY_DATA
#undef MODELDATA_EXTRA
#undef CUSTOM_SCREENS_DATA
#undef SPLASH_MODE
#undef EXTRA_GENERAL_FIELDS
#undef THEME_DATA
#undef NOBACKUP
#if !defined(BACKUP)
/* Compile time check to test structure size has not changed *
Changing the size of one of the eeprom structs may cause wrong data to
be loaded. Error out if the struct size changes.
This function tries not avoid checking or using the defines
other than the CPU arch and board type so changes in other
defines also trigger the struct size changes */
template <typename ToCheck, size_t expectedSize, size_t realSize = sizeof(ToCheck)>
void check_size() {
static_assert(expectedSize == realSize, "struct size changed");
}
static inline void check_struct()
{
#define CHKSIZE(x, y) check_size<struct x, y>()
#define CHKTYPE(x, y) check_size<x, y>()
#if defined(CPUARM)
CHKSIZE(CurveRef, 2);
#endif
/* Difference between Taranis/Horus is LEN_EXPOMIX_NAME */
/* Sky9x does not have virtualinputs */
/* LEN_FUNCTION_NAME is the difference in CustomFunctionData */
#if defined(PCBACAIR)
#elif defined(PCBX7)
CHKSIZE(MixData, 20);
CHKSIZE(ExpoData, 17);
CHKSIZE(LimitData, 11);
CHKSIZE(LogicalSwitchData, 9);
CHKSIZE(CustomFunctionData, 11);
CHKSIZE(FlightModeData, 36);
CHKSIZE(TimerData, 11);
CHKSIZE(SwashRingData, 8);
CHKSIZE(FrSkyBarData, 6);
CHKSIZE(FrSkyLineData, 4);
CHKTYPE(union FrSkyScreenData, 24);
CHKSIZE(FrSkyTelemetryData, 106);
CHKSIZE(ModelHeader, 12);
CHKSIZE(CurveData, 4);
CHKSIZE(RadioData, 850);
CHKSIZE(ModelData, 6025);
#elif defined(PCBTARANIS)
CHKSIZE(MixData, 22);
CHKSIZE(ExpoData, 19);
CHKSIZE(LimitData, 13);
CHKSIZE(LogicalSwitchData, 9);
CHKSIZE(CustomFunctionData, 11);
CHKSIZE(FlightModeData, 40);
CHKSIZE(TimerData, 16);
CHKSIZE(SwashRingData, 8);
CHKSIZE(FrSkyBarData, 6);
CHKSIZE(FrSkyLineData, 6);
CHKTYPE(union FrSkyScreenData, 24);
CHKSIZE(FrSkyTelemetryData, 106);
CHKSIZE(ModelHeader, 24);
CHKSIZE(CurveData, 4);
#if defined(PCBX9E)
CHKSIZE(RadioData, 952);
CHKSIZE(ModelData, 6520);
#else
CHKSIZE(RadioData, 872);
CHKSIZE(ModelData, 6507);
#endif
#elif defined(PCBFLAMENCO)
#elif defined(PCBHORUS)
CHKSIZE(MixData, 20);
CHKSIZE(ExpoData, 17);
CHKSIZE(LimitData, 13);
CHKSIZE(CustomFunctionData, 9);
CHKSIZE(FlightModeData, 44);
CHKSIZE(TimerData, 16);
CHKSIZE(SwashRingData, 8);
CHKSIZE(FrSkyTelemetryData, 7);
CHKSIZE(ModelHeader, 27);
CHKSIZE(CurveData, 4);
CHKSIZE(RadioData, 847);
CHKSIZE(ModelData, 9380);
CHKSIZE(CustomScreenData, 610);
CHKSIZE(Topbar::PersistentData, 216);
#elif defined(PCBSKY9X)
CHKSIZE(MixData, 20);
CHKSIZE(ExpoData, 17);
CHKSIZE(LimitData, 11);
CHKSIZE(CustomFunctionData, 9);
CHKSIZE(FlightModeData, 38);
CHKSIZE(TimerData, 11);
CHKSIZE(SwashRingData, 8);
CHKSIZE(FrSkyBarData, 5);
CHKSIZE(FrSkyLineData, 2);
CHKSIZE(FrSkyTelemetryData, 90);
CHKSIZE(ModelHeader, 12);
CHKTYPE(CurveData, 4);
CHKSIZE(RadioData, 727);
CHKSIZE(ModelData, 5188);
#else
// Common for all variants
CHKSIZE(LimitData, 5);
CHKSIZE(SwashRingData, 3);
CHKSIZE(FrSkyBarData, 3);
CHKSIZE(FrSkyLineData, 2);
CHKSIZE(FrSkyTelemetryData, 43);
CHKSIZE(ModelHeader, 11);
CHKTYPE(CurveData, 1);
// AVR
#if defined(CPUM2560) || defined(CPUM2561)
CHKSIZE(ExpoData, 5);
CHKSIZE(MixData, 10);
#else
CHKSIZE(MixData, 9);
CHKSIZE(ExpoData, 4);
#endif
#if defined(CPUM2560)
CHKSIZE(CustomFunctionData, 4);
CHKSIZE(TimerData, 6);
#else
CHKSIZE(CustomFunctionData, 3);
CHKSIZE(TimerData, 3);
#endif
#if defined(PCBSTD)
CHKSIZE(FlightModeData, 13);
CHKSIZE(RadioData, 84);
#else
CHKSIZE(FlightModeData, 30);
CHKSIZE(RadioData, 85);
#endif
#endif /* board specific ifdefs*/
#if defined(CPUARM)
CHKSIZE(LogicalSwitchData, 9);
#if !defined(COLORLCD)
CHKSIZE(FrSkyChannelData, 7);
#endif
CHKSIZE(TelemetrySensor, 13);
CHKSIZE(ModuleData,70);
#else
CHKSIZE(LogicalSwitchData, 3);
CHKSIZE(FrSkyChannelData, 6);
CHKSIZE(ModuleData, 38);
#endif
#if !defined(PCBSTD)
CHKSIZE(GVarData, 7);
#endif
CHKSIZE(FrSkyRSSIAlarm, 1);
CHKSIZE(TrainerData, 16);
#undef CHKSIZE
#undef CHKSIZEUNION
}
#endif /* BACKUP */