Files
edgetx-gx12/radio/src/datastructs_private.h
T
Raphael CoefficandMalte Langermann 2b100e0eb5 refact: ADC, switches and keys
Add "hardware_defs" target to dump hardware defines from hal.h per target

Fixed hal.h definitions for switches & ADC inputs

Tools to generate hardware definitions from current hal.h

generator: add support for EXTx and analog switches

WiP

Add generated header to hardware_defs target

Add support for ADC input direction and index per GPIO port

Incredible: it compiles

Removed StdPeriph ADC driver

Works on QX7

Works on TX16S (VBat missing)

Switch driver using generated switches for stm32 targets

Switch driver with generated switches for simu

Use switch names from switch driver

Fixed single conversion handling

Fixed horus VBat reading

Added switch name

Fix warnings about bitfield offsets and GCC 4.4

This is caused by bitfields that cross type boundaries. In this particular case, it happens as the bitfield is not defined the same in `rtc_backup.cpp`.

Switches has already been moved to generic driver

Jitter measurement for each sample, not just for oversampled values

Moved periph clock init to the ADC driver

ADC & GPIOs.

Add switchInit() to init pins

Fix NV14 CMake

Fix taranis target

Fix NV14 (again)

Model audio files: use new interface for switch index

Fix X9-lite

Fix simu headers

Fix getSwitchName()

Add support for ADC switches

Fix switch warning YAML

Test only switches which are defined

Conversions tests for QX7 only on QX7

Fix X12S

Fix function switch names

Enable ADC periph clock before initialising channels

NV14: offset inputs for the sticks & fix switches

WiP: get rid of VSRCRAW and some more

Simu shall use normal ADC driver

fix x7

fix nv14

Fix 9x nav

fix 212x64

fix xlite

fix x9e

fix simu lib

fix unit tests

fix x7 tests

PWM stick values should be written directly into adcValues

... just like FlySky sticks.

fix x12s

fix nv14

Add some support for SPI ADC (only unit tests)

Remove `jq` usage

fix generate_yaml.py for newer libclang

fix pot config

fix stick names

Some YAML generator improvements

Max 16 Pots on COLORLCD

Fix some source names

Use 10 bits for switches to prevent overflow

Removed horus constants for switches & ADC inputs

Fix unit tests

Fix curve edit

Fix libsimulator

Fix function switches (tpro)

Refine ADC & analog API

Moved hardware definitions scripts and templates into own dir

cleanup API refine

Fix unit tests

Mixer: apply calibration only on required inputs

Place ADC switches after all other ADC inputs

Fix X12S

Remove useless TR_POTS_VSRCRAW, TR_SW_VSRCRAW, and TR_VSRCRAW

Cleanup redundant generated YAML parsers

Fixes Boxer rebase

Add boxer to generate-hw-defs.sh

Obsolete LUA exports

Add boxer ADC_DIRECTION

Split generate_hw_defs.py into multiple files

Some cleanup (+ LUA switches)

Fix AXIS definitions

Fixed translation strings declarations

Some rebase fixes

Remove some useless StdPeriph drivers

fix: set pin mode to reset state on usart deinit

fix: use canonical names for calibration data

fix: ADC driver does not care about unconfigured inputs

fix X12S ADC

Add support for ADC conversion chaining

Better X12S ADC implem

Moved X12S ADC driver to HAL/LL

Improve ADC driver separation

Fixed taranis & nv14

Moved PWM gimbals to HAL/LL

Removed useless TR_EXTRA_VSRCRAW

Fixed include guards

Small fixes

Renamed control inputs

Moved internal and external module pulse driver def to boards

Move more things to the generic_stm32 board

Remove STR_VMIXTRIMS

Added analog labels

Generate main control names

Misuse labels / short labels for main controls

Backward compatibility: sliders and legacy names

New keys driver

Let's get rid of StdPeriph headers in simu

Add jinja2 to CI workflows

Use `grep` instead of `sed`

chore: add python jinja2 oto msys setup script

Removed more static definitions and use dynamic ones instead

Fixes X9E

Fix x7 nav too

212 switch display

Fix default sliders

Removed NUM_STICKS

212 switch display working nicely

Surface radio 'stick' replacements

fix: switch, trim & rotary pin init

Remove old key drivers

Removed VKEYS

Removed ETX_FOURCC

Fixed SURFACE_NAME

Removed TR_VSWITCHES & TR_TRIMS_SWITCHES

Fix xpot switches

Store calibrated analogs in physical order

Use getSourceString in drawSource

Implement missing YAML read/write

Fix isSourceAvailableInInputs()

Fix isSourceAvailable()

Some surface fixes

Fix CLI debug

Ported colour UI of analog diagnostics to new ADC API

Small fixes

Better input mapping

Minor tpro fixes

Fix trims available

Remove TX mode choice on surface radio

Rename surface controls

Channel order alignement

Fix throttle warning

Fix checkTrims()

Fix pot config casting issue

Fix IS_SWITCH_FS()

Fixed input mapping

Fix fswitch auto-switch

Fixed storing / reading function switches in YAML

Fix enableVBatBridge() / disableVBatBridge()

Fix interesting mode conversion

Fix sources issues

Fix special funnction list

Proper function switch handling

128 GUI improvements

Fix compilation

Boxer cosmetics

128 hardware screen cosmetic

Fix TX12 switches

More switches fixes

Simplify CPU type handling

Fix flash size

Fixed page-up / page-down in libopenui
2023-06-25 14:32:39 +02:00

992 lines
26 KiB
C

/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* 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 "board.h"
#include "dataconstants.h"
#include "definitions.h"
#include "opentx_types.h"
#include "globals.h"
#include "serial.h"
#include "usb_joystick.h"
#include "input_mapping.h"
#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
#include "storage/yaml/yaml_defs.h"
/*
* Mixer structure
*/
PACK(struct CurveRef {
uint8_t type;
int8_t value CUST(in_read_weight,in_write_weight);
});
PACK(struct MixData {
int16_t weight:11 CUST(in_read_weight,in_write_weight); // GV1=-1024, -GV1=1023
uint16_t destCh:5;
uint16_t srcRaw:10 CUST(r_mixSrcRaw,w_mixSrcRaw); // srcRaw=0 means not used
uint16_t carryTrim:1;
uint16_t mixWarn:2; // mixer warning
uint16_t mltpx:2 ENUM(MixerMultiplex);
uint16_t spare:1 SKIP;
int32_t offset:13 CUST(in_read_weight,in_write_weight);
int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc);
uint32_t flightModes:9 CUST(r_flightModes, w_flightModes);
CurveRef curve;
uint8_t delayUp;
uint8_t delayDown;
uint8_t speedUp;
uint8_t speedDown;
NOBACKUP(char name[LEN_EXPOMIX_NAME]);
});
/*
* Expo/Input structure
*/
PACK(struct ExpoData {
uint16_t mode:2;
uint16_t scale:14;
CUST_ATTR(carryTrim, r_carryTrim, nullptr); //pre 2.9
int16_t trimSource:6;
uint16_t srcRaw:10 ENUM(MixSources) CUST(r_mixSrcRaw,w_mixSrcRaw);
uint32_t chn:5;
int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc);
uint32_t flightModes:9 CUST(r_flightModes, w_flightModes);
int32_t weight:8 CUST(in_read_weight,in_write_weight);
NOBACKUP(char name[LEN_EXPOMIX_NAME]);
int8_t offset CUST(in_read_weight,in_write_weight);
CurveRef curve;
});
/*
* Limit structure
*/
PACK(struct LimitData {
int32_t min:11 CUST(in_read_weight,in_write_weight);
int32_t max:11 CUST(in_read_weight,in_write_weight);
int32_t ppmCenter:10; // TODO can be reduced to 8 bits
int16_t offset:11 CUST(in_read_weight,in_write_weight);
uint16_t symetrical:1;
uint16_t revert:1;
uint16_t spare:3 SKIP;
int8_t curve;
NOBACKUP(char name[LEN_CHANNEL_NAME]);
});
/*
* LogicalSwitch structure
*/
PACK(struct LogicalSwitchData {
uint8_t func ENUM(LogicalSwitchesFunctions);
CUST_ATTR(def,r_logicSw,w_logicSw);
int32_t v1:10 SKIP;
int32_t v3:10 SKIP;
int32_t andsw:10 CUST(r_swtchSrc,w_swtchSrc); // TODO rename to xswtch
uint32_t andswtype:1 SKIP; // TODO rename to xswtchType (AND / OR)
uint32_t spare:1 SKIP; // anything else needed?
int16_t v2 SKIP;
uint8_t delay;
uint8_t duration;
});
/*
* SpecialFunction structure
*/
#if defined(PCBTARANIS)
#define CFN_SPARE_TYPE int32_t
#else
#define CFN_SPARE_TYPE int16_t
#endif
PACK(struct CustomFunctionData {
int16_t swtch:10 CUST(r_swtchSrc,w_swtchSrc);
uint16_t func:6 ENUM(Functions); // TODO: 6 bits for Functions?
CUST_ATTR(def,r_customFn,w_customFn);
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;
NOBACKUP(PACK(struct {
int32_t val1;
NOBACKUP(CFN_SPARE_TYPE val2);
}) clear);
}) NAME(fp) SKIP;
uint8_t active SKIP;
bool isEmpty() const
{
return swtch == 0;
}
});
/*
* FlightMode structure
*/
PACK(struct trim_t {
int16_t value:11;
uint16_t mode:5;
});
PACK(struct FlightModeData {
trim_t trim[MAX_TRIMS];
NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
// swtch of phase[0] is not used
int16_t swtch:10 ENUM(SwitchSources) CUST(r_swtchSrc,w_swtchSrc);
int16_t spare:6 SKIP;
uint8_t fadeIn;
uint8_t fadeOut;
gvar_t gvars[MAX_GVARS] FUNC(gvar_is_active);
});
/*
* Curve structure
*/
PACK(struct CurveHeader {
uint8_t type:1;
uint8_t smooth:1;
int8_t points:6; // describes number of points - 5
NOBACKUP(char name[LEN_CURVE_NAME]);
});
/*
* GVar structure
*/
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 SKIP;
});
/*
* Timer structure
*/
PACK(struct TimerData {
uint32_t start:22;
int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc);
int32_t value:22;
uint32_t mode:3 ENUM(TimerModes);
uint32_t countdownBeep:2;
uint32_t minuteBeep:1;
uint32_t persistent:2;
int32_t countdownStart:2;
uint8_t showElapsed:1;
uint8_t extraHaptic:1;
uint8_t spare:6 SKIP;
NOBACKUP(char name[LEN_TIMER_NAME]);
});
/*
* Swash Ring structure
*/
PACK(struct SwashRingData {
uint8_t type ENUM(SwashType);
uint8_t value;
uint8_t collectiveSource CUST(r_mixSrcRaw,w_mixSrcRaw);
uint8_t aileronSource CUST(r_mixSrcRaw,w_mixSrcRaw);
uint8_t elevatorSource CUST(r_mixSrcRaw,w_mixSrcRaw);
int8_t collectiveWeight;
int8_t aileronWeight;
int8_t elevatorWeight;
});
#if MAX_SCRIPTS > 0
union ScriptDataInput {
int16_t value;
source_t source CUST(r_mixSrcRaw,w_mixSrcRaw);
} FUNC(select_script_input);
PACK(struct ScriptData {
char file[LEN_SCRIPT_FILENAME];
char name[LEN_SCRIPT_NAME];
ScriptDataInput inputs[MAX_SCRIPT_INPUTS];
});
#endif
/*
* Frsky Telemetry structure (legacy read-only)
*/
PACK(struct RssiAlarmData {
// int8_t disabled:1;
CUST_ATTR(disabled,r_rssiDisabled,nullptr);
// int8_t warning:6; + 45
CUST_ATTR(warning,r_rssiWarning,nullptr);
// int8_t critical:6; + 42
CUST_ATTR(critical,r_rssiCritical,nullptr);
});
PACK(struct RFAlarmData {
int8_t warning;
int8_t critical;
});
typedef int16_t ls_telemetry_value_t;
#if !defined(COLORLCD)
PACK(struct FrSkyBarData {
source_t source CUST(r_mixSrcRaw,w_mixSrcRaw);
ls_telemetry_value_t barMin; // minimum for bar display
ls_telemetry_value_t barMax; // ditto for max display (would usually = ratio)
});
// This is used to be able to use
// custom read/write functions in
// an array made of typdef'ed literal types
// (YAML generator)
#if defined(YAML_GENERATOR)
PACK(struct LineDataSource {
source_t val CUST(r_mixSrcRaw,w_mixSrcRaw);
});
PACK(struct FrSkyLineData {
LineDataSource sources[NUM_LINE_ITEMS];
});
#else
// This here is the real structure used at run-time
PACK(struct FrSkyLineData {
source_t sources[NUM_LINE_ITEMS];
});
#endif
#if defined(PCBTARANIS)
PACK(struct TelemetryScriptData {
char file[LEN_SCRIPT_FILENAME];
int16_t inputs[MAX_TELEM_SCRIPT_INPUTS];
});
#endif
#if defined(YAML_GENERATOR)
union TelemetryScreenData_u {
FrSkyBarData bars[4];
FrSkyLineData lines[4];
#if defined(PCBTARANIS)
TelemetryScriptData script;
#endif
};
PACK(struct TelemetryScreenData {
CUST_ATTR(type,r_tele_screen_type,w_tele_screen_type);
TelemetryScreenData_u u FUNC(select_tele_screen_data);
});
#else
union TelemetryScreenData {
FrSkyBarData bars[4];
FrSkyLineData lines[4];
#if defined(PCBTARANIS)
TelemetryScriptData script;
#endif
} FUNC(select_tele_screen_data);
#endif
#endif
PACK(struct VarioData {
uint8_t source:7 CUST(r_tele_sensor,w_tele_sensor); // telemetry sensor idx + 1
uint8_t centerSilent:1;
int8_t centerMax;
int8_t centerMin;
int8_t min;
int8_t max;
});
/*
* Telemetry Sensor structure
*/
#define TELEMETRY_ENDPOINT_NONE 0xFF
#define TELEMETRY_ENDPOINT_SPORT 0x07
PACK(struct TelemetrySensor {
union {
uint16_t id; // data identifier, for FrSky we can reuse existing ones.
// Source unit is derived from type.
NOBACKUP(uint16_t persistentValue);
} NAME(id1) FUNC(select_id1);
union {
NOBACKUP(PACK(struct {
uint8_t physID:5;
uint8_t rxIndex:3; // 1 bit for module index, 2 bits for receiver index
}) frskyInstance);
uint8_t instance;
NOBACKUP(uint8_t formula ENUM(TelemetrySensorFormula));
} NAME(id2) FUNC(select_id2);
NOBACKUP(char label[TELEM_LABEL_LEN]); // user defined label
uint8_t subId;
uint8_t type:1 ENUM(TelemetrySensorType); // 0=custom / 1=calculated
// user can choose what unit to display each value in
uint8_t spare1:1 SKIP;
uint8_t unit:6;
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 spare2:1 SKIP;
union {
NOBACKUP(PACK(struct {
uint16_t ratio;
int16_t offset;
}) custom);
NOBACKUP(PACK(struct {
uint8_t source;
uint8_t index;
uint16_t spare SKIP;
}) cell);
NOBACKUP(PACK(struct {
int8_t sources[4];
}) calc);
NOBACKUP(PACK(struct {
uint8_t source;
uint8_t spare[3] SKIP;
}) consumption);
NOBACKUP(PACK(struct {
uint8_t gps;
uint8_t alt;
uint16_t spare SKIP;
}) dist);
uint32_t param;
} NAME(cfg) FUNC(select_sensor_cfg);
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;
bool isSameInstance(TelemetryProtocol protocol, uint8_t instance);
);
});
/*
* Trainer module structure
*/
PACK(struct TrainerModuleData {
uint8_t mode CUST(r_trainerMode,w_trainerMode);
uint8_t channelsStart;
int8_t channelsCount; // 0=8 channels
int8_t frameLength;
int8_t delay:6;
uint8_t pulsePol:1;
uint8_t spare2:1 SKIP;
});
/*
* Module structure
*/
PACK(struct PpmModule {
int8_t delay:6;
uint8_t pulsePol:1;
uint8_t outputType:1; // false = open drain, true = push pull
int8_t frameLength;
});
PACK(struct ModuleData {
uint8_t type ENUM(ModuleType);
CUST_ATTR(subType,r_modSubtype,w_modSubtype);
uint8_t channelsStart;
int8_t channelsCount CUST(r_channelsCount,w_channelsCount); // 0=8 channels
uint8_t failsafeMode:4 ENUM(FailsafeModes); // only 3 bits used
uint8_t subType:4 SKIP;
union {
uint8_t raw[PXX2_MAX_RECEIVERS_PER_MODULE * PXX2_LEN_RX_NAME + 1];
NOBACKUP(PpmModule ppm);
NOBACKUP(struct {
uint8_t rfProtocol SKIP;
uint8_t disableTelemetry:1;
uint8_t disableMapping:1;
uint8_t autoBindMode:1;
uint8_t lowPowerMode:1;
uint8_t receiverTelemetryOff:1;
uint8_t receiverHigherChannels:1;
uint8_t spare:2 SKIP;
int8_t optionValue;
} multi);
NOBACKUP(struct {
uint8_t power:2; // 0=10 mW, 1=100 mW, 2=500 mW, 3=1W
uint8_t spare1:2 SKIP;
uint8_t receiverTelemetryOff:1; // false = receiver telem enabled
uint8_t receiverHigherChannels:1; // false = pwm out 1-8, true 9-16
int8_t antennaMode:2;
uint8_t spare2 SKIP;
} pxx);
NOBACKUP(struct {
uint8_t spare1:6 SKIP;
uint8_t noninverted:1;
uint8_t spare2:1 SKIP;
int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms)
} sbus);
NOBACKUP(struct {
uint8_t receivers:7; // 4 bits spare
uint8_t racingMode:1;
char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME];
} pxx2);
NOBACKUP(struct {
uint8_t rx_id[4];
uint8_t mode:3;
uint8_t rfPower:1;
uint8_t reserved:4;
uint8_t rx_freq[2];
void setDefault() {
rx_id[0] = rx_id[1] = rx_id[2] = rx_id[3] = 0;
mode = 3;
rfPower = 0;
rx_freq[0] = 50;
rx_freq[1] = 0;
}
} flysky);
NOBACKUP(struct {
uint8_t emi:2;
uint8_t telemetry:1;
uint8_t phyMode:3;
uint8_t reserved:2;
uint8_t rfPower;
} afhds3);
NOBACKUP(struct {
uint8_t raw12bits:1;
uint8_t telemetryBaudrate:3;
uint8_t spare1:4 SKIP;
} ghost);
NOBACKUP(struct {
uint8_t telemetryBaudrate:3;
} crsf);
NOBACKUP(struct {
uint8_t flags;
} dsmp);
} NAME(mod) FUNC(select_mod_type);
NOBACKUP(inline uint8_t getChannelsCount() const
{
return channelsCount + 8;
})
});
/*
* Model structure
*/
#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(STORAGE_MODELSLIST)
char labels[LABELS_LENGTH];
#endif
});
// 2 bits per switch, max 32 switches
static_assert(sizeof(swconfig_t) >= (MAX_SWITCHES * 2 + 7) / 8,
"MAX_SWITCHES must fit swconfig_t");
static_assert(sizeof(swarnstate_t) >= (MAX_SWITCHES * 2 + 7) / 8,
"MAX_SWITCHES must fit swarnstate_t");
// pot config: 4 bits per pot
static_assert(sizeof(potconfig_t) * 8 >= ((MAX_POTS - 1) / 4) + 1,
"MAX_POTS must fit potconfig_t");
// pot warning enabled: 1 bit per pot
static_assert(sizeof(potwarnen_t) * 8 >= MAX_POTS,
"MAX_POTS must fit potwarnen_t");
#if defined(COLORLCD) && defined(BACKUP)
#define CUSTOM_SCREENS_DATA
#elif defined(COLORLCD)
#include "gui/colorlcd/layout.h"
#include "gui/colorlcd/topbar.h"
#define LAYOUT_ID_LEN 12
PACK(struct CustomScreenData {
char LayoutId[LAYOUT_ID_LEN];
LayoutPersistentData layoutData;
});
#define CUSTOM_SCREENS_DATA \
NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]); \
NOBACKUP(TopBarPersistentData topbarData); \
NOBACKUP(uint8_t view);
#else
#define CUSTOM_SCREENS_DATA \
uint8_t screensType SKIP; /* 2bits per screen (None/Gauges/Numbers/Script) */ \
TelemetryScreenData screens[MAX_TELEMETRY_SCREENS]; \
uint8_t view;
#endif
#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E)
// telemetry sensor idx + 1
#define TOPBAR_DATA \
NOBACKUP(uint8_t voltsSource CUST(r_tele_sensor,w_tele_sensor)); \
NOBACKUP(uint8_t altitudeSource CUST(r_tele_sensor,w_tele_sensor));
#else
#define TOPBAR_DATA
#endif
#if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBNV14)
#define SCRIPT_DATA \
NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]);
#else
#define SCRIPT_DATA
#endif
#if defined(FUNCTION_SWITCHES)
#define FUNCTION_SWITCHS_FIELDS \
uint16_t functionSwitchConfig; \
uint16_t functionSwitchGroup; \
uint16_t functionSwitchStartConfig; \
uint8_t functionSwitchLogicalState; \
char switchNames[NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME];
#else
#define FUNCTION_SWITCHS_FIELDS
#endif
PACK(struct PartialModel {
ModelHeader header;
TimerData timers[MAX_TIMERS];
});
/*
* USB Joystick channel structure
*/
PACK(struct USBJoystickChData {
uint8_t mode:3 ENUM(USBJoystickCh);
uint8_t inversion:1;
uint8_t param:4;
uint8_t btn_num:5;
uint8_t switch_npos:3;
#if defined(USBJ_EX)
NOBACKUP(
uint8_t btnCount() {
// Use one less joystick button for 2POS and 3POS switches for Companion mode
if ((param == USBJOYS_BTN_MODE_COMPANION) && (switch_npos > 0) && (switch_npos < 3))
return switch_npos;
return switch_npos + 1;
}
uint8_t lastBtnNumNoCLip() {
uint8_t last = btn_num + switch_npos;
// Use one less joystick button for 2POS and 3POS switches for Companion mode
if ((param == USBJOYS_BTN_MODE_COMPANION) && (switch_npos > 0) && (switch_npos < 3)) last -= 1;
return last;
}
uint8_t lastBtnNum() {
uint8_t last = lastBtnNumNoCLip();
if (last >= USBJ_BUTTON_SIZE) {
last = USBJ_BUTTON_SIZE - 1;
}
return last;
}
);
#endif
});
PACK(struct ModelData {
CUST_ATTR(semver,nullptr,w_semver);
ModelHeader header;
TimerData timers[MAX_TIMERS];
uint8_t telemetryProtocol:3;
uint8_t thrTrim:1; // Enable Throttle Trim
uint8_t noGlobalFunctions:1;
uint8_t displayTrims:2;
uint8_t ignoreSensorIds:1;
int8_t trimInc:3; // Trim Increments
uint8_t disableThrottleWarning:1;
uint8_t displayChecklist:1;
uint8_t extendedLimits:1;
uint8_t extendedTrims:1;
uint8_t throttleReversed:1;
uint8_t enableCustomThrottleWarning:1;
uint8_t disableTelemetryWarning:1;
uint8_t showInstanceIds:1;
uint8_t spare3:5 SKIP;
int8_t customThrottleWarningPosition;
BeepANACenter beepANACenter;
MixData mixData[MAX_MIXERS] NO_IDX;
LimitData limitData[MAX_OUTPUT_CHANNELS];
ExpoData expoData[MAX_EXPOS] NO_IDX;
CurveHeader curves[MAX_CURVES];
int8_t points[MAX_CURVE_POINTS];
LogicalSwitchData logicalSw[MAX_LOGICAL_SWITCHES];
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS] FUNC(cfn_is_active);
SwashRingData swashR FUNC(swash_is_active);
FlightModeData flightModeData[MAX_FLIGHT_MODES] FUNC(fmd_is_active);
NOBACKUP(uint8_t thrTraceSrc CUST(r_thrSrc,w_thrSrc));
CUST_ATTR(switchWarningState, r_swtchWarn, w_swtchWarn);
NOBACKUP(swarnstate_t switchWarningState SKIP);
GVarData gvars[MAX_GVARS];
NOBACKUP(VarioData varioData);
NOBACKUP(uint8_t rssiSource CUST(r_tele_sensor,w_tele_sensor));
TOPBAR_DATA
#if defined(YAML_GENERATOR)
RssiAlarmData rssiAlarms;
#endif
NOBACKUP(RFAlarmData rfAlarms);
uint8_t thrTrimSw:3;
uint8_t potsWarnMode:2 ENUM(PotsWarnMode);
NOBACKUP(uint8_t jitterFilter:2 ENUM(ModelOverridableEnable));
uint8_t spare1:1 SKIP;
ModuleData moduleData[NUM_MODULES];
int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
TrainerModuleData trainerData;
SCRIPT_DATA
NOBACKUP(char inputNames[MAX_INPUTS][LEN_INPUT_NAME]);
NOBACKUP(potwarnen_t potsWarnEnabled);
NOBACKUP(int8_t potsWarnPosition[MAX_POTS]);
NOBACKUP(TelemetrySensor telemetrySensors[MAX_TELEMETRY_SENSORS];)
TARANIS_PCBX9E_FIELD(uint8_t toplcdTimer)
CUSTOM_SCREENS_DATA
char modelRegistrationID[PXX2_LEN_REGISTRATION_ID];
FUNCTION_SWITCHS_FIELDS
uint8_t getThrottleStickTrimSource() const
{
// Makes Throttle the default (=0)
auto thr = inputMappingGetThrottle();
if (thrTrimSw == 0) {
return MIXSRC_FIRST_TRIM + thr;
} else if (thrTrimSw == thr) {
return MIXSRC_FIRST_TRIM;
} else {
return MIXSRC_FIRST_TRIM + thrTrimSw;
}
}
void setThrottleStickTrimSource(int16_t src)
{
auto thr = inputMappingGetThrottle();
if (src == MIXSRC_FIRST_TRIM + thr) {
thrTrimSw = 0;
} else if (src == MIXSRC_FIRST_TRIM) {
thrTrimSw = thr;
} else {
thrTrimSw = src - MIXSRC_FIRST_TRIM;
}
}
uint8_t usbJoystickExtMode:1;
uint8_t usbJoystickIfMode:3 ENUM(USBJoystickIfMode);
uint8_t usbJoystickCircularCut:4;
USBJoystickChData usbJoystickCh[USBJ_MAX_JOYSTICK_CHANNELS];
// Radio level tabs control (model settings)
#if defined(COLORLCD)
uint8_t radioThemesDisabled:2 ENUM(ModelOverridableEnable);
#endif
uint8_t radioGFDisabled:2 ENUM(ModelOverridableEnable);
uint8_t radioTrainerDisabled:2 ENUM(ModelOverridableEnable);
// Model level tabs control (model setting)
uint8_t modelHeliDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelFMDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelCurvesDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelGVDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelLSDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelSFDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelCustomScriptsDisabled:2 ENUM(ModelOverridableEnable);
uint8_t modelTelemetryDisabled:2 ENUM(ModelOverridableEnable);
});
/*
* Radio structure
*/
#if XPOTS_MULTIPOS_COUNT > 0
PACK(struct StepsCalibData {
uint8_t count;
uint8_t steps[XPOTS_MULTIPOS_COUNT-1];
});
#endif
PACK(struct CalibData {
CUST_IDX(calib, r_calib, w_calib);
int16_t mid;
int16_t spanNeg;
int16_t spanPos;
});
PACK(struct TrainerMix {
uint8_t srcChn:6; // 0-7 = ch1-8
uint8_t mode:2 ENUM(TrainerMultiplex); // off,add-mode,subst-mode
int8_t studWeight;
});
PACK(struct TrainerData {
int16_t calib[4];
NOBACKUP(TrainerMix mix[4]);
});
#if defined(COLORLCD)
#define SPLASH_MODE uint8_t splashSpares:3 SKIP
#else
#define SPLASH_MODE int8_t splashMode:3
#endif
#if defined(COLORLCD)
#define EXTRA_GENERAL_FIELDS \
NOBACKUP(char currModelFilename[LEN_MODEL_FILENAME+1]); \
NOBACKUP(uint8_t modelQuickSelect:1); \
NOBACKUP(uint8_t blOffBright:7); \
NOBACKUP(char bluetoothName[LEN_BLUETOOTH_NAME]);
#else
#if defined(STORAGE_BLUETOOTH)
#define BLUETOOTH_FIELDS \
uint8_t spare6 SKIP; \
char bluetoothName[LEN_BLUETOOTH_NAME];
#else
#define BLUETOOTH_FIELDS
#endif
#define EXTRA_GENERAL_FIELDS \
uint8_t backlightColor; \
BLUETOOTH_FIELDS
#endif
#if defined(COLORLCD) && !defined(BACKUP)
#include "theme.h"
#define THEME_NAME_LEN 8
#define THEME_DATA \
NOBACKUP(char themeName[THEME_NAME_LEN]); \
NOBACKUP(OpenTxTheme::PersistentData themeData);
#else
#define THEME_DATA
#endif
#if defined(BUZZER)
#define BUZZER_FIELD 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 int8_t spare2:2 SKIP
#endif
PACK(struct RadioData {
// Real attributes
NOBACKUP(uint8_t manuallyEdited:1);
NOBACKUP(int8_t spare0:7 SKIP);
CUST_ATTR(semver,nullptr,w_semver);
CUST_ATTR(board,nullptr,w_board);
CalibData calib[MAX_CALIB_ANALOG_INPUTS] NO_IDX;
NOBACKUP(uint16_t chkSum SKIP);
N_HORUS_FIELD(int8_t currModel);
N_HORUS_FIELD(uint8_t contrast);
NOBACKUP(uint8_t vBatWarn);
NOBACKUP(int8_t txVoltageCalibration);
uint8_t backlightMode:3 ENUM(BacklightMode);
int8_t antennaMode:2 ENUM(AntennaModes);
uint8_t disableRtcWarning:1;
uint8_t keysBacklight:1;
uint8_t spare1:1 SKIP;
uint8_t internalModule ENUM(ModuleType);
NOBACKUP(TrainerData trainer);
NOBACKUP(uint8_t view); // index of view in main screen
NOBACKUP(BUZZER_FIELD); /* 2bits */
NOBACKUP(uint8_t fai:1);
NOBACKUP(int8_t beepMode:2 ENUM(BeeperMode) CUST(r_beeperMode,w_beeperMode));
NOBACKUP(uint8_t alarmsFlash:1);
NOBACKUP(uint8_t disableMemoryWarning:1);
NOBACKUP(uint8_t disableAlarmWarning:1);
uint8_t stickMode:2;
int8_t timezone:5;
uint8_t adjustRTC:1;
NOBACKUP(uint8_t inactivityTimer);
CUST_ATTR(telemetryBaudrate, r_telemetryBaudrate, nullptr);
uint8_t internalModuleBaudrate:3;
SPLASH_MODE; /* 3bits */
int8_t hapticMode:2 CUST(r_beeperMode,w_beeperMode);
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 CUST(r_5pos,w_5pos));
NOBACKUP(int8_t beepLength:3 CUST(r_5pos,w_5pos));
NOBACKUP(int8_t hapticStrength:3 CUST(r_5pos,w_5pos));
NOBACKUP(uint8_t gpsFormat:1);
NOBACKUP(uint8_t unexpectedShutdown:1 SKIP);
NOBACKUP(uint8_t speakerPitch CUST(r_spPitch,w_spPitch));
NOBACKUP(int8_t speakerVolume CUST(r_vol,w_vol));
NOBACKUP(int8_t vBatMin CUST(r_vbat_min,w_vbat_min));
NOBACKUP(int8_t vBatMax CUST(r_vbat_max,w_vbat_max));
NOBACKUP(uint8_t backlightBright);
NOBACKUP(uint32_t globalTimer);
NOBACKUP(uint8_t bluetoothBaudrate:4);
NOBACKUP(uint8_t bluetoothMode:4 ENUM(BluetoothModes));
NOBACKUP(uint8_t countryCode:2);
NOBACKUP(int8_t pwrOnSpeed:3);
NOBACKUP(int8_t pwrOffSpeed:3);
CUST_ATTR(jitterFilter, r_jitterFilter, nullptr);
NOBACKUP(uint8_t noJitterFilter:1); /* 0 - Jitter filter active */
NOBACKUP(uint8_t imperial:1);
NOBACKUP(uint8_t disableRssiPoweroffAlarm:1);
NOBACKUP(uint8_t USBMode:2);
NOBACKUP(uint8_t jackMode:2);
NOBACKUP(uint8_t sportUpdatePower:1 SKIP);
NOBACKUP(char ttsLanguage[2]);
NOBACKUP(int8_t beepVolume:4 CUST(r_5pos,w_5pos));
NOBACKUP(int8_t wavVolume:4 CUST(r_5pos,w_5pos));
NOBACKUP(int8_t varioVolume:4 CUST(r_5pos,w_5pos));
NOBACKUP(int8_t backgroundVolume:4 CUST(r_5pos,w_5pos));
NOBACKUP(int8_t varioPitch CUST(r_vPitch,w_vPitch));
NOBACKUP(int8_t varioRange CUST(r_vPitch,w_vPitch));
NOBACKUP(int8_t varioRepeat);
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS] FUNC(cfn_is_active);
CUST_ATTR(auxSerialMode, r_serialMode, nullptr);
CUST_ATTR(aux2SerialMode, r_serialMode, nullptr);
NOBACKUP(uint32_t serialPort ARRAY(SERIAL_CONF_BITS_PER_PORT,struct_serialConfig,nullptr));
CUST_ARRAY(sticksConfig, struct_stickConfig, MAX_STICKS, stick_name_valid);
CUST_ARRAY(slidersConfig, struct_sliderConfig, MAX_POTS, nullptr);
potconfig_t potsConfig ARRAY(4,struct_potConfig,nullptr);
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr);
EXTRA_GENERAL_FIELDS
THEME_DATA
char ownerRegistrationID[PXX2_LEN_REGISTRATION_ID];
CUST_ATTR(rotEncDirection, r_rotEncDirection, nullptr);
NOBACKUP(uint8_t rotEncMode:2);
NOBACKUP(int8_t uartSampleMode:2); // See UartSampleModes
#if defined(STICK_DEAD_ZONE)
NOBACKUP(uint8_t stickDeadZone:3);
#else
NOBACKUP(uint8_t stickDeadZoneSpare:3 SKIP);
#endif
NOBACKUP(uint8_t spare4:1 SKIP);
#if defined(IMU)
NOBACKUP(int8_t imuMax);
NOBACKUP(int8_t imuOffset);
#endif
#if defined(COLORLCD)
NOBACKUP(char selectedTheme[SELECTED_THEME_NAME_LEN]);
#endif
// Radio level tabs control (global settings)
#if defined(COLORLCD)
uint8_t radioThemesDisabled:1;
#endif
uint8_t radioGFDisabled:1;
uint8_t radioTrainerDisabled:1;
// Model level tabs control (global setting)
uint8_t modelHeliDisabled:1;
uint8_t modelFMDisabled:1;
uint8_t modelCurvesDisabled:1;
uint8_t modelGVDisabled:1;
uint8_t modelLSDisabled:1;
uint8_t modelSFDisabled:1;
uint8_t modelCustomScriptsDisabled:1;
uint8_t modelTelemetryDisabled:1;
});
#undef SWITCHES_WARNING_DATA
#undef MODEL_GVARS_DATA
#undef TELEMETRY_DATA
#undef SCRIPTS_DATA
#undef CUSTOM_SCREENS_DATA
#undef SPLASH_MODE
#undef EXTRA_GENERAL_FIELDS
#undef THEME_DATA
#undef NOBACKUP