compiled with the FRSKY_STICKS option enabled, the FW is lighter than without the option!
2743 lines
99 KiB
C++
2743 lines
99 KiB
C++
#include <stdlib.h>
|
|
#include <algorithm>
|
|
#include "helpers.h"
|
|
#include "opentxeeprom.h"
|
|
#include <QObject>
|
|
|
|
#define IS_DBLEEPROM(board, version) ((board==BOARD_GRUVIN9X || board==BOARD_M128) && version >= 213)
|
|
// Macro used for Gruvin9x board and M128 board between versions 213 and 214 (when there were stack overflows!)
|
|
#define IS_DBLRAM(board, version) ((board==BOARD_GRUVIN9X && version >= 213) || (board==BOARD_M128 && version >= 213 && version <= 214))
|
|
|
|
#define HAS_PERSISTENT_TIMERS(board) (IS_ARM(board) || board == BOARD_GRUVIN9X)
|
|
#define HAS_LARGE_LCD(board) IS_TARANIS(board)
|
|
#define MAX_VIEWS(board) (HAS_LARGE_LCD(board) ? 2 : 256)
|
|
#define MAX_POTS(board) (IS_TARANIS(board) ? 5 : 3)
|
|
#define MAX_SWITCHES(board) (IS_TARANIS(board) ? 8 : 7)
|
|
#define MAX_SWITCHES_POSITION(board) (IS_TARANIS(board) ? 22 : 9)
|
|
#define MAX_ROTARY_ENCODERS(board) (board==BOARD_GRUVIN9X ? 2 : (board==BOARD_SKY9X ? 1 : 0))
|
|
#define MAX_PHASES(board, version) (IS_ARM(board) ? 9 : (IS_DBLRAM(board, version) ? 6 : 5))
|
|
#define MAX_MIXERS(board, version) (IS_ARM(board) ? 64 : 32)
|
|
#define MAX_CHANNELS(board, version) (IS_ARM(board) ? 32 : 16)
|
|
#define MAX_EXPOS(board, version) (IS_ARM(board) ? ((IS_TARANIS(board) && version >= 216) ? 64 : 32) : (IS_DBLRAM(board, version) ? 16 : 14))
|
|
#define MAX_CUSTOM_SWITCHES(board, version) (IS_ARM(board) ? 32 : (IS_DBLEEPROM(board, version) ? 15 : 12))
|
|
#define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? (version >= 216 ? 64 : 32) : (IS_DBLEEPROM(board, version) ? 24 : 16))
|
|
#define MAX_CURVES(board, version) (IS_ARM(board) ? ((IS_TARANIS(board) && version >= 216) ? 32 : 16) : O9X_MAX_CURVES)
|
|
#define MAX_GVARS(board, version) ((IS_ARM(board) && version >= 216) ? 9 : 5)
|
|
#define NUM_PPM_INPUTS(board, version) ((IS_ARM(board) && version >= 216) ? 16 : 8)
|
|
|
|
#define IS_AFTER_RELEASE_21_MARCH_2013(board, version) (version >= 214 || (!IS_ARM(board) && version >= 213))
|
|
#define IS_AFTER_RELEASE_23_MARCH_2013(board, version) (version >= 214 || (board==BOARD_STOCK && version >= 213))
|
|
|
|
inline int switchIndex(int i, BoardEnum board, unsigned int version)
|
|
{
|
|
bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version);
|
|
if (!IS_TARANIS(board) && afterrelease21March2013)
|
|
return (i<=3 ? i+3 : (i<=6 ? i-3 : i));
|
|
else
|
|
return i;
|
|
}
|
|
|
|
class SwitchesConversionTable: public ConversionTable {
|
|
|
|
public:
|
|
SwitchesConversionTable(BoardEnum board, unsigned int version, unsigned long flags=0)
|
|
{
|
|
int val=0;
|
|
int offset=0;
|
|
if (flags & POPULATE_TIMER_MODES) {
|
|
offset = 4;
|
|
for (int i=0; i<5; i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_TIMER_MODE, i), val++);
|
|
}
|
|
}
|
|
else {
|
|
addConversion(RawSwitch(SWITCH_TYPE_NONE), val++);
|
|
}
|
|
|
|
for (int i=1; i<=MAX_SWITCHES_POSITION(board); i++) {
|
|
int s = switchIndex(i, board, version);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, -s), -val+offset);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, s), val++);
|
|
}
|
|
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
for (int i=1; i<=3*6; i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_MULTIPOS_POT, -i), -val+offset);
|
|
addConversion(RawSwitch(SWITCH_TYPE_MULTIPOS_POT, i), val++);
|
|
}
|
|
}
|
|
|
|
if (version >= 216) {
|
|
for (int i=1; i<=8; i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_TRIM, -i), -val+offset);
|
|
addConversion(RawSwitch(SWITCH_TYPE_TRIM, i), val++);
|
|
}
|
|
}
|
|
|
|
if (version >= 216) {
|
|
for (int i=1; i<=MAX_ROTARY_ENCODERS(board); i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_ROTARY_ENCODER, -i), -val+offset);
|
|
addConversion(RawSwitch(SWITCH_TYPE_ROTARY_ENCODER, i), val++);
|
|
}
|
|
}
|
|
|
|
for (int i=1; i<=MAX_CUSTOM_SWITCHES(board, version); i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, -i), -val+offset);
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, i), val++);
|
|
}
|
|
|
|
if (!(flags & POPULATE_TIMER_MODES)) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_OFF), -val+offset);
|
|
addConversion(RawSwitch(SWITCH_TYPE_ON), val++);
|
|
}
|
|
|
|
if (version < 216) {
|
|
// previous "moment" switches
|
|
for (int i=1; i<=MAX_SWITCHES_POSITION(board); i++) {
|
|
int s = switchIndex(i, board, version);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, s), val++);
|
|
}
|
|
|
|
for (int i=1; i<=MAX_CUSTOM_SWITCHES(board, version); i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, i), val++);
|
|
}
|
|
|
|
// previous "One" switch
|
|
addConversion(RawSwitch(SWITCH_TYPE_ON), val++);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
void addConversion(const RawSwitch & sw, const int b)
|
|
{
|
|
ConversionTable::addConversion(sw.toValue(), b);
|
|
}
|
|
|
|
class Cache {
|
|
public:
|
|
Cache(BoardEnum board, unsigned int version, unsigned long flags, SwitchesConversionTable * table):
|
|
board(board),
|
|
version(version),
|
|
flags(flags),
|
|
table(table)
|
|
{
|
|
}
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
unsigned long flags;
|
|
SwitchesConversionTable * table;
|
|
};
|
|
|
|
static std::list<Cache> internalCache;
|
|
|
|
public:
|
|
|
|
static SwitchesConversionTable * getInstance(BoardEnum board, unsigned int version, unsigned long flags=0)
|
|
{
|
|
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
|
|
Cache element = *it;
|
|
if (element.board == board && element.version == version && element.flags == flags)
|
|
return element.table;
|
|
}
|
|
|
|
Cache element(board, version, flags, new SwitchesConversionTable(board, version, flags));
|
|
internalCache.push_back(element);
|
|
return element.table;
|
|
}
|
|
static void Cleanup()
|
|
{
|
|
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
|
|
Cache element = *it;
|
|
delete element.table;
|
|
}
|
|
internalCache.clear();
|
|
}
|
|
};
|
|
|
|
std::list<SwitchesConversionTable::Cache> SwitchesConversionTable::internalCache;
|
|
|
|
#define FLAG_NONONE 0x01
|
|
#define FLAG_NOSWITCHES 0x02
|
|
#define FLAG_NOTELEMETRY 0x04
|
|
|
|
class SourcesConversionTable: public ConversionTable {
|
|
|
|
public:
|
|
SourcesConversionTable(BoardEnum board, unsigned int version, unsigned int variant, unsigned long flags=0)
|
|
{
|
|
bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version);
|
|
|
|
int val=0;
|
|
|
|
if (!(flags & FLAG_NONONE)) {
|
|
addConversion(RawSource(SOURCE_TYPE_NONE), val++);
|
|
}
|
|
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
for (int i=0; i<32; i++)
|
|
addConversion(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i), val++);
|
|
for (int i=0; i<7; i++) {
|
|
for (int j=0; j<6; j++) {
|
|
addConversion(RawSource(SOURCE_TYPE_LUA_INPUT, i*16+j), val++);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i=0; i<4+MAX_POTS(board); i++) {
|
|
if (IS_TARANIS(board) && version < 216 && i==6)
|
|
continue;
|
|
addConversion(RawSource(SOURCE_TYPE_STICK, i), val++);
|
|
}
|
|
|
|
for (int i=0; i<MAX_ROTARY_ENCODERS(board); i++)
|
|
addConversion(RawSource(SOURCE_TYPE_ROTARY_ENCODER, 0), val++);
|
|
|
|
if (!afterrelease21March2013) {
|
|
for (int i=0; i<NUM_STICKS; i++)
|
|
addConversion(RawSource(SOURCE_TYPE_TRIM, i), val++);
|
|
}
|
|
|
|
addConversion(RawSource(SOURCE_TYPE_MAX), val++);
|
|
|
|
if (afterrelease21March2013) {
|
|
for (int i=0; i<3; i++)
|
|
addConversion(RawSource(SOURCE_TYPE_CYC, i), val++);
|
|
}
|
|
|
|
if (afterrelease21March2013) {
|
|
for (int i=0; i<NUM_STICKS; i++)
|
|
addConversion(RawSource(SOURCE_TYPE_TRIM, i), val++);
|
|
}
|
|
|
|
addConversion(RawSource(SOURCE_TYPE_SWITCH, 0), val++);
|
|
|
|
if (!(flags & FLAG_NOSWITCHES)) {
|
|
if (afterrelease21March2013) {
|
|
for (int i=1; i<MAX_SWITCHES(board); i++)
|
|
addConversion(RawSource(SOURCE_TYPE_SWITCH, i), val++);
|
|
}
|
|
else {
|
|
for (int i=1; i<=9; i++) {
|
|
if (i>=4 && i<=6)
|
|
addConversion(RawSource(SOURCE_TYPE_SWITCH, 0), val++);
|
|
else
|
|
addConversion(RawSource(SOURCE_TYPE_SWITCH, i), val++);
|
|
}
|
|
}
|
|
for (int i=0; i<MAX_CUSTOM_SWITCHES(board, version); i++)
|
|
addConversion(RawSource(SOURCE_TYPE_CUSTOM_SWITCH, i), val++);
|
|
}
|
|
|
|
if (!afterrelease21March2013) {
|
|
for (int i=0; i<3; i++)
|
|
addConversion(RawSource(SOURCE_TYPE_CYC, i), val++);
|
|
}
|
|
|
|
for (int i=0; i<NUM_PPM_INPUTS(board, version); i++)
|
|
addConversion(RawSource(SOURCE_TYPE_PPM, i), val++);
|
|
|
|
for (int i=0; i<MAX_CHANNELS(board, version); i++)
|
|
addConversion(RawSource(SOURCE_TYPE_CH, i), val++);
|
|
|
|
if (!(flags & FLAG_NOTELEMETRY)) {
|
|
if (afterrelease21March2013) {
|
|
if ((board != BOARD_STOCK && (board!=BOARD_M128 || version<215)) || (variant & GVARS_VARIANT)) {
|
|
for (int i=0; i<MAX_GVARS(board, version); i++)
|
|
addConversion(RawSource(SOURCE_TYPE_GVAR, i), val++);
|
|
}
|
|
}
|
|
|
|
for (int i=0; i<TELEMETRY_SOURCE_ACC; i++) {
|
|
if (version < 216) {
|
|
if (i==TELEMETRY_SOURCE_SWR || i==TELEMETRY_SOURCE_RX_BATT || i==TELEMETRY_SOURCE_A3 || i==TELEMETRY_SOURCE_A4 || i==TELEMETRY_SOURCE_ASPD || i==TELEMETRY_SOURCE_DTE || i==TELEMETRY_SOURCE_CELL_MIN || i==TELEMETRY_SOURCE_CELLS_MIN || i==TELEMETRY_SOURCE_VFAS_MIN)
|
|
continue;
|
|
}
|
|
if (!IS_ARM(board)) {
|
|
if (i==TELEMETRY_SOURCE_SWR|| i==TELEMETRY_SOURCE_RX_BATT || i==TELEMETRY_SOURCE_A3 || i==TELEMETRY_SOURCE_A4 || i==TELEMETRY_SOURCE_A3_MIN || i==TELEMETRY_SOURCE_A4_MIN)
|
|
continue;
|
|
}
|
|
addConversion(RawSource(SOURCE_TYPE_TELEMETRY, i), val++);
|
|
if (version >= 216 && IS_ARM(board)) {
|
|
if (i==TELEMETRY_SOURCE_DTE)
|
|
val += 5;
|
|
if (i==TELEMETRY_SOURCE_POWER_MAX)
|
|
val += 5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
void addConversion(const RawSource & source, const int b)
|
|
{
|
|
ConversionTable::addConversion(source.toValue(), b);
|
|
}
|
|
|
|
class Cache {
|
|
public:
|
|
Cache(BoardEnum board, unsigned int version, unsigned int variant, unsigned long flags, SourcesConversionTable * table):
|
|
board(board),
|
|
version(version),
|
|
variant(variant),
|
|
flags(flags),
|
|
table(table)
|
|
{
|
|
}
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
unsigned int variant;
|
|
unsigned long flags;
|
|
SourcesConversionTable * table;
|
|
};
|
|
static std::list<Cache> internalCache;
|
|
|
|
public:
|
|
|
|
static SourcesConversionTable * getInstance(BoardEnum board, unsigned int version, unsigned int variant, unsigned long flags=0)
|
|
{
|
|
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
|
|
Cache element = *it;
|
|
if (element.board == board && element.version == version && element.variant == variant && element.flags == flags)
|
|
return element.table;
|
|
}
|
|
|
|
Cache element(board, version, variant, flags, new SourcesConversionTable(board, version, variant, flags));
|
|
internalCache.push_back(element);
|
|
return element.table;
|
|
}
|
|
static void Cleanup()
|
|
{
|
|
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
|
|
Cache element = *it;
|
|
delete element.table;
|
|
}
|
|
internalCache.clear();
|
|
}
|
|
};
|
|
|
|
std::list<SourcesConversionTable::Cache> SourcesConversionTable::internalCache;
|
|
|
|
void OpenTxEepromCleanup(void)
|
|
{
|
|
SourcesConversionTable::Cleanup();
|
|
SwitchesConversionTable::Cleanup();
|
|
}
|
|
|
|
ThrottleSourceConversionTable::ThrottleSourceConversionTable(BoardEnum board, unsigned int version)
|
|
{
|
|
int val=0;
|
|
|
|
addConversion(THROTTLE_SOURCE_THR, val++);
|
|
|
|
if (IS_TARANIS(board)) {
|
|
addConversion(THROTTLE_SOURCE_S1, val++);
|
|
addConversion(THROTTLE_SOURCE_S2, val++);
|
|
if (version >= 216)
|
|
addConversion(THROTTLE_SOURCE_S3, val++);
|
|
addConversion(THROTTLE_SOURCE_LS, val++);
|
|
addConversion(THROTTLE_SOURCE_RS, val++);
|
|
}
|
|
else {
|
|
addConversion(THROTTLE_SOURCE_P1, val++);
|
|
addConversion(THROTTLE_SOURCE_P2, val++);
|
|
addConversion(THROTTLE_SOURCE_P3, val++);
|
|
}
|
|
|
|
for (int i=0; i<MAX_CHANNELS(board, version); i++) {
|
|
addConversion(THROTTLE_SOURCE_FIRST_CHANNEL+i, val++);
|
|
}
|
|
}
|
|
|
|
|
|
template <int N>
|
|
class SwitchField: public ConversionField< SignedField<N> > {
|
|
public:
|
|
SwitchField(RawSwitch & sw, BoardEnum board, unsigned int version, unsigned long flags=0):
|
|
ConversionField< SignedField<N> >(_switch, SwitchesConversionTable::getInstance(board, version, flags), "Switch"),
|
|
sw(sw),
|
|
_switch(0)
|
|
{
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
_switch = sw.toValue();
|
|
ConversionField< SignedField<N> >::beforeExport();
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
ConversionField< SignedField<N> >::afterImport();
|
|
sw = RawSwitch(_switch);
|
|
}
|
|
|
|
protected:
|
|
RawSwitch & sw;
|
|
int _switch;
|
|
};
|
|
|
|
class TelemetrySourcesConversionTable: public ConversionTable {
|
|
|
|
public:
|
|
TelemetrySourcesConversionTable(BoardEnum board, unsigned int version)
|
|
{
|
|
int val = 0;
|
|
|
|
if (IS_AFTER_RELEASE_21_MARCH_2013(board, version)) {
|
|
addConversion(0, val++);
|
|
}
|
|
|
|
addConversion(1+TELEMETRY_SOURCE_TX_BATT, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_TIMER1, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_TIMER2, val++);
|
|
if (IS_ARM(board) && version >= 216)
|
|
addConversion(1+TELEMETRY_SOURCE_SWR, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_RSSI_TX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_RSSI_RX, val++);
|
|
if (IS_ARM(board) && version >= 216)
|
|
addConversion(1+TELEMETRY_SOURCE_RX_BATT, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_A1, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_A2, val++);
|
|
if (IS_ARM(board) && version >= 216) {
|
|
addConversion(1+TELEMETRY_SOURCE_A3, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_A4, val++);
|
|
}
|
|
addConversion(1+TELEMETRY_SOURCE_ALT, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_RPM, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_FUEL, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_T1, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_T2, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_SPEED, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_DIST, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_GPS_ALT, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_CELL, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_CELLS_SUM, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_VFAS, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_CURRENT, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_CONSUMPTION, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_POWER, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_ACCX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_ACCY, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_ACCZ, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_HDG, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_VERTICAL_SPEED, val++);
|
|
if (version >= 216) {
|
|
addConversion(1+TELEMETRY_SOURCE_ASPD, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_DTE, val++);
|
|
}
|
|
if (IS_ARM(board) && version >= 216) {
|
|
for (int i=0; i<5; i++)
|
|
addConversion(1+TELEMETRY_SOURCE_RESERVE, val++);
|
|
}
|
|
addConversion(1+TELEMETRY_SOURCE_A1_MIN, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_A2_MIN, val++);
|
|
if (IS_ARM(board) && version >= 216) {
|
|
addConversion(1+TELEMETRY_SOURCE_A3_MIN, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_A4_MIN, val++);
|
|
}
|
|
addConversion(1+TELEMETRY_SOURCE_ALT_MIN, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_ALT_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_RPM_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_T1_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_T2_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_SPEED_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_DIST_MAX, val++);
|
|
if (version >= 216) {
|
|
addConversion(1+TELEMETRY_SOURCE_ASPEED_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_CELL_MIN, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_CELLS_MIN, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_VFAS_MIN, val++);
|
|
}
|
|
addConversion(1+TELEMETRY_SOURCE_CURRENT_MAX, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_POWER_MAX, val++);
|
|
if (IS_ARM(board) && version >= 216) {
|
|
for (int i=0; i<5; i++)
|
|
addConversion(1+TELEMETRY_SOURCE_RESERVE, val++);
|
|
}
|
|
addConversion(1+TELEMETRY_SOURCE_ACC, val++);
|
|
addConversion(1+TELEMETRY_SOURCE_GPS_TIME, val++);
|
|
}
|
|
};
|
|
|
|
template <int N>
|
|
class TelemetrySourceField: public ConversionField< UnsignedField<N> > {
|
|
public:
|
|
TelemetrySourceField(unsigned int & source, BoardEnum board, unsigned int version):
|
|
ConversionField< UnsignedField<N> >(source, &conversionTable, "Telemetry source"),
|
|
conversionTable(board, version),
|
|
source(source),
|
|
board(board),
|
|
version(version)
|
|
{
|
|
}
|
|
|
|
protected:
|
|
TelemetrySourcesConversionTable conversionTable;
|
|
unsigned int & source;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
};
|
|
|
|
template <int N>
|
|
class SourceField: public ConversionField< UnsignedField<N> > {
|
|
public:
|
|
SourceField(RawSource & source, BoardEnum board, unsigned int version, unsigned int variant, unsigned long flags=0):
|
|
ConversionField< UnsignedField<N> >(_source, SourcesConversionTable::getInstance(board, version, variant, flags), "Source"),
|
|
source(source),
|
|
_source(0)
|
|
{
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
_source = source.toValue();
|
|
ConversionField< UnsignedField<N> >::beforeExport();
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
ConversionField< UnsignedField<N> >::afterImport();
|
|
source = RawSource(_source);
|
|
}
|
|
|
|
protected:
|
|
RawSource & source;
|
|
unsigned int _source;
|
|
};
|
|
|
|
|
|
int smallGvarToEEPROM(int gvar)
|
|
{
|
|
if (gvar < -10000) {
|
|
gvar = 128 + gvar + 10000;
|
|
}
|
|
else if (gvar > 10000) {
|
|
gvar = -128 +gvar - 10001;
|
|
}
|
|
return gvar;
|
|
}
|
|
|
|
int smallGvarToC9x(int gvar)
|
|
{
|
|
if (gvar>110) {
|
|
gvar = gvar-128 - 10000;
|
|
}
|
|
else if (gvar<-110) {
|
|
gvar = gvar+128 + 10001;
|
|
}
|
|
return gvar;
|
|
}
|
|
|
|
void splitGvarParam(const int gvar, int & _gvar, unsigned int & _gvarParam, const BoardEnum board, const int version)
|
|
{
|
|
if (version >= 214 || (!IS_ARM(board) && version >= 213)) {
|
|
if (gvar < -10000) {
|
|
_gvarParam = 0;
|
|
_gvar = 256 + gvar + 10000;
|
|
}
|
|
else if (gvar > 10000) {
|
|
_gvarParam = 1;
|
|
_gvar = gvar - 10001;
|
|
}
|
|
else {
|
|
if (gvar < 0) _gvarParam = 1;
|
|
else _gvarParam = 0;
|
|
_gvar = gvar; // save routine throws away all unused bits; therefore no 2er complement compensation needed here
|
|
}
|
|
}
|
|
else {
|
|
if (gvar < -10000) {
|
|
_gvarParam = 1;
|
|
_gvar = gvar + 10000;
|
|
}
|
|
else if (gvar > 10000) {
|
|
_gvarParam = 1;
|
|
_gvar = gvar - 10001;
|
|
}
|
|
else {
|
|
_gvarParam = 0;
|
|
_gvar = gvar;
|
|
}
|
|
}
|
|
}
|
|
|
|
void concatGvarParam(int & gvar, const int _gvar, const unsigned int _gvarParam, const BoardEnum board, const int version)
|
|
{
|
|
if (version >= 214 || (!IS_ARM(board) && version >= 213)) {
|
|
gvar = _gvar;
|
|
if (gvar<0) gvar+=256; // remove 2er complement, because 8bit part is in this case unsigned
|
|
if (_gvarParam) { // here is the real sign bit
|
|
gvar|=-256; // set all higher bits to simulate negative value
|
|
}
|
|
|
|
if (gvar>245) {
|
|
gvar = gvar-256 - 10000;
|
|
} else if (gvar<-245) {
|
|
gvar = gvar+256 + 10001;
|
|
}
|
|
}
|
|
else {
|
|
if (_gvarParam == 0) {
|
|
gvar = _gvar;
|
|
}
|
|
else if (_gvar >= 0) {
|
|
gvar = 10001 + _gvar;
|
|
}
|
|
else {
|
|
gvar = -10000 + _gvar;
|
|
}
|
|
}
|
|
}
|
|
|
|
void exportGvarParam(const int gvar, int & _gvar, int version)
|
|
{
|
|
int GV1 = (version >= 216 ? 4096 : 512);
|
|
|
|
if (gvar < -10000) {
|
|
_gvar = GV1 + gvar + 10000;
|
|
}
|
|
else if (gvar > 10000) {
|
|
_gvar = GV1 + gvar - 10001;
|
|
}
|
|
else {
|
|
_gvar = gvar;
|
|
}
|
|
}
|
|
|
|
void importGvarParam(int & gvar, const int _gvar, int version)
|
|
{
|
|
int GV1 = (version >= 216 ? 4096 : 512);
|
|
|
|
if (_gvar >= GV1) {
|
|
gvar = 10001 + _gvar - GV1;
|
|
}
|
|
else if (_gvar >= GV1-9) {
|
|
gvar = -10000 + _gvar - GV1;
|
|
}
|
|
else if (_gvar < -GV1) {
|
|
gvar = -10000 + _gvar + GV1 + 1;
|
|
}
|
|
else if (_gvar < -GV1+9) {
|
|
gvar = 10000 + _gvar + GV1 + 1;
|
|
}
|
|
else {
|
|
gvar = _gvar;
|
|
}
|
|
|
|
// qDebug() << QString("import") << _gvar << gvar;
|
|
}
|
|
|
|
class CurveReferenceField: public TransformedField {
|
|
public:
|
|
CurveReferenceField(CurveReference & curve, BoardEnum board, unsigned int version):
|
|
TransformedField(internalField),
|
|
curve(curve),
|
|
_curve_type(0),
|
|
_curve_value(0)
|
|
{
|
|
internalField.Append(new UnsignedField<8>(_curve_type));
|
|
internalField.Append(new SignedField<8>(_curve_value));
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
if (curve.value != 0) {
|
|
_curve_type = (unsigned int)curve.type;
|
|
_curve_value = smallGvarToEEPROM(curve.value);
|
|
}
|
|
else {
|
|
_curve_type = 0;
|
|
_curve_value = 0;
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
curve.type = (CurveReference::CurveRefType)_curve_type;
|
|
curve.value = smallGvarToC9x(_curve_value);
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
CurveReference & curve;
|
|
unsigned int _curve_type;
|
|
int _curve_value;
|
|
};
|
|
|
|
class HeliField: public StructField {
|
|
public:
|
|
HeliField(SwashRingData & heli, BoardEnum board, unsigned int version, unsigned int variant)
|
|
{
|
|
Append(new BoolField<1>(heli.invertELE));
|
|
Append(new BoolField<1>(heli.invertAIL));
|
|
Append(new BoolField<1>(heli.invertCOL));
|
|
Append(new UnsignedField<5>(heli.type));
|
|
Append(new SourceField<8>(heli.collectiveSource, board, version, variant));
|
|
//, FLAG_NOSWITCHES)); Fix shift in collective
|
|
Append(new UnsignedField<8>(heli.value));
|
|
}
|
|
};
|
|
|
|
class FlightModeField: public TransformedField {
|
|
public:
|
|
FlightModeField(PhaseData & phase, int index, BoardEnum board, unsigned int version):
|
|
TransformedField(internalField),
|
|
internalField("Phase"),
|
|
phase(phase),
|
|
index(index),
|
|
board(board),
|
|
version(version),
|
|
rotencCount(IS_ARM(board) ? 1 : (board == BOARD_GRUVIN9X ? 2 : 0))
|
|
{
|
|
if (board == BOARD_STOCK || (board==BOARD_M128 && version>=215)) {
|
|
// On stock we use 10bits per trim
|
|
for (int i=0; i<NUM_STICKS; i++)
|
|
internalField.Append(new SignedField<8>(trimBase[i]));
|
|
for (int i=0; i<NUM_STICKS; i++)
|
|
internalField.Append(new SignedField<2>(trimExt[i]));
|
|
}
|
|
else if (board == BOARD_TARANIS && version >= 216) {
|
|
for (int i=0; i<NUM_STICKS; i++) {
|
|
internalField.Append(new SignedField<11>(phase.trim[i]));
|
|
internalField.Append(new UnsignedField<5>(trimMode[i]));
|
|
}
|
|
}
|
|
else {
|
|
for (int i=0; i<NUM_STICKS; i++) {
|
|
internalField.Append(new SignedField<16>(trimBase[i]));
|
|
}
|
|
}
|
|
|
|
internalField.Append(new SwitchField<8>(phase.swtch, board, version));
|
|
if (HAS_LARGE_LCD(board))
|
|
internalField.Append(new ZCharField<10>(phase.name));
|
|
else
|
|
internalField.Append(new ZCharField<6>(phase.name));
|
|
|
|
if (IS_ARM(board) && version >= 214) {
|
|
internalField.Append(new UnsignedField<8>(phase.fadeIn));
|
|
internalField.Append(new UnsignedField<8>(phase.fadeOut));
|
|
}
|
|
else {
|
|
internalField.Append(new UnsignedField<4>(phase.fadeIn));
|
|
internalField.Append(new UnsignedField<4>(phase.fadeOut));
|
|
}
|
|
|
|
for (int i=0; i<rotencCount; i++) {
|
|
internalField.Append(new SignedField<16>(phase.rotaryEncoders[i]));
|
|
}
|
|
|
|
if (board != BOARD_STOCK && (board != BOARD_M128 || version < 215)) {
|
|
for (int i=0; i<MAX_GVARS(board, version); i++) {
|
|
internalField.Append(new SignedField<16>(phase.gvars[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
for (int i=0; i<NUM_STICKS; i++) {
|
|
if (board == BOARD_TARANIS && version >= 216) {
|
|
if (phase.trimMode[i] < 0)
|
|
trimMode[i] = TRIM_MODE_NONE;
|
|
else
|
|
trimMode[i] = 2*phase.trimRef[i] + phase.trimMode[i];
|
|
}
|
|
else {
|
|
int trim;
|
|
if (phase.trimMode[i] < 0)
|
|
trim = 0;
|
|
else if (phase.trimRef[i] != index)
|
|
trim = 501 + phase.trimRef[i] - (phase.trimRef[i] > index ? 1 : 0);
|
|
else
|
|
trim = std::max(-500, std::min(500, phase.trim[i]));
|
|
if (board == BOARD_STOCK || (board == BOARD_M128 && version >= 215)) {
|
|
trimBase[i] = trim >> 2;
|
|
trimExt[i] = (trim & 0x03);
|
|
}
|
|
else {
|
|
trimBase[i] = trim;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
for (int i=0; i<NUM_STICKS; i++) {
|
|
if (board == BOARD_TARANIS && version >= 216) {
|
|
if (trimMode[i] == TRIM_MODE_NONE) {
|
|
phase.trimMode[i] = -1;
|
|
}
|
|
else {
|
|
phase.trimMode[i] = trimMode[i] % 2;
|
|
phase.trimRef[i] = trimMode[i] / 2;
|
|
}
|
|
}
|
|
else {
|
|
if (phase.swtch == RawSwitch(SWITCH_TYPE_NONE)) {
|
|
phase.trimRef[i] = 0;
|
|
phase.trimMode[i] = 0;
|
|
phase.trim[i] = 0;
|
|
}
|
|
else {
|
|
int trim;
|
|
if (board == BOARD_STOCK || (board == BOARD_M128 && version >= 215))
|
|
trim = ((trimBase[i]) << 2) + (trimExt[i] & 0x03);
|
|
else
|
|
trim = trimBase[i];
|
|
if (trim > 500) {
|
|
phase.trimRef[i] = trim - 501;
|
|
if (phase.trimRef[i] >= index)
|
|
phase.trimRef[i] += 1;
|
|
phase.trimMode[i] = 0;
|
|
phase.trim[i] = 0;
|
|
}
|
|
else {
|
|
phase.trimRef[i] = index/*own trim*/;
|
|
phase.trimMode[i] = 0;
|
|
phase.trim[i] = trim;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
PhaseData & phase;
|
|
int index;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
int rotencCount;
|
|
int trimBase[NUM_STICKS];
|
|
int trimExt[NUM_STICKS];
|
|
unsigned int trimMode[NUM_STICKS];
|
|
};
|
|
|
|
class MixField: public TransformedField {
|
|
public:
|
|
MixField(MixData & mix, BoardEnum board, unsigned int version, ModelData * model):
|
|
TransformedField(internalField),
|
|
internalField("Mix"),
|
|
mix(mix),
|
|
board(board),
|
|
version(version),
|
|
model(model)
|
|
{
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
internalField.Append(new UnsignedField<8>(_destCh));
|
|
internalField.Append(new UnsignedField<16>(mix.phases));
|
|
internalField.Append(new UnsignedField<2>((unsigned int &)mix.mltpx));
|
|
internalField.Append(new UnsignedField<1>((unsigned int &)mix.carryTrim));
|
|
internalField.Append(new SpareBitsField<5>());
|
|
internalField.Append(new SignedField<16>(_weight));
|
|
internalField.Append(new SwitchField<8>(mix.swtch, board, version));
|
|
internalField.Append(new CurveReferenceField(mix.curve, board, version));
|
|
internalField.Append(new UnsignedField<4>(mix.mixWarn));
|
|
internalField.Append(new SpareBitsField<4>());
|
|
internalField.Append(new UnsignedField<8>(mix.delayUp));
|
|
internalField.Append(new UnsignedField<8>(mix.delayDown));
|
|
internalField.Append(new UnsignedField<8>(mix.speedUp));
|
|
internalField.Append(new UnsignedField<8>(mix.speedDown));
|
|
internalField.Append(new SourceField<8>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
|
|
internalField.Append(new SignedField<16>(_offset));
|
|
internalField.Append(new ZCharField<8>(mix.name));
|
|
internalField.Append(new SpareBitsField<8>());
|
|
}
|
|
else if (IS_ARM(board) && version >= 216) {
|
|
internalField.Append(new UnsignedField<4>(_destCh));
|
|
internalField.Append(new UnsignedField<4>(mix.mixWarn));
|
|
internalField.Append(new UnsignedField<16>(mix.phases));
|
|
internalField.Append(new BoolField<1>(_curveMode));
|
|
internalField.Append(new BoolField<1>(mix.noExpo));
|
|
internalField.Append(new SignedField<3>(mix.carryTrim));
|
|
internalField.Append(new UnsignedField<2>((unsigned int &)mix.mltpx));
|
|
internalField.Append(new SpareBitsField<1>());
|
|
internalField.Append(new SignedField<16>(_weight));
|
|
internalField.Append(new SwitchField<8>(mix.swtch, board, version));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
internalField.Append(new UnsignedField<8>(mix.delayUp));
|
|
internalField.Append(new UnsignedField<8>(mix.delayDown));
|
|
internalField.Append(new UnsignedField<8>(mix.speedUp));
|
|
internalField.Append(new UnsignedField<8>(mix.speedDown));
|
|
internalField.Append(new SourceField<8>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
|
|
internalField.Append(new SignedField<16>(_offset));
|
|
internalField.Append(new ZCharField<6>(mix.name));
|
|
}
|
|
else if (IS_ARM(board)) {
|
|
internalField.Append(new UnsignedField<8>(_destCh));
|
|
internalField.Append(new UnsignedField<16>(mix.phases));
|
|
internalField.Append(new BoolField<1>(_curveMode));
|
|
internalField.Append(new BoolField<1>(mix.noExpo));
|
|
internalField.Append(new SignedField<3>(mix.carryTrim));
|
|
internalField.Append(new UnsignedField<2>((unsigned int &)mix.mltpx));
|
|
if (version >= 214)
|
|
internalField.Append(new SpareBitsField<1>());
|
|
else
|
|
internalField.Append(new UnsignedField<1>(_offsetMode));
|
|
internalField.Append(new SignedField<16>(_weight));
|
|
internalField.Append(new SwitchField<8>(mix.swtch, board, version));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
if (version >= 214) {
|
|
internalField.Append(new UnsignedField<4>(mix.mixWarn));
|
|
internalField.Append(new SpareBitsField<4>());
|
|
}
|
|
else {
|
|
internalField.Append(new UnsignedField<8>(mix.mixWarn));
|
|
}
|
|
internalField.Append(new UnsignedField<8>(mix.delayUp));
|
|
internalField.Append(new UnsignedField<8>(mix.delayDown));
|
|
internalField.Append(new UnsignedField<8>(mix.speedUp));
|
|
internalField.Append(new UnsignedField<8>(mix.speedDown));
|
|
internalField.Append(new SourceField<8>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
|
|
if (version >= 214)
|
|
internalField.Append(new SignedField<16>(_offset));
|
|
else
|
|
internalField.Append(new SignedField<8>(_offset));
|
|
if (HAS_LARGE_LCD(board)) {
|
|
internalField.Append(new ZCharField<8>(mix.name));
|
|
internalField.Append(new SpareBitsField<16>());
|
|
}
|
|
else {
|
|
internalField.Append(new ZCharField<6>(mix.name));
|
|
}
|
|
}
|
|
else if (IS_DBLRAM(board, version) && IS_AFTER_RELEASE_23_MARCH_2013(board, version)) {
|
|
internalField.Append(new UnsignedField<4>(_destCh));
|
|
internalField.Append(new BoolField<1>(_curveMode));
|
|
internalField.Append(new BoolField<1>(mix.noExpo));
|
|
internalField.Append(new UnsignedField<1>(_weightMode));
|
|
internalField.Append(new UnsignedField<1>(_offsetMode));
|
|
internalField.Append(new SourceField<8>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
|
|
internalField.Append(new SignedField<8>(_weight));
|
|
internalField.Append(new SwitchField<8>(mix.swtch, board, version));
|
|
internalField.Append(new UnsignedField<8>(mix.phases));
|
|
internalField.Append(new UnsignedField<2>((unsigned int &)mix.mltpx));
|
|
internalField.Append(new SignedField<3>(mix.carryTrim));
|
|
internalField.Append(new UnsignedField<2>(mix.mixWarn));
|
|
internalField.Append(new SpareBitsField<1>());
|
|
internalField.Append(new UnsignedField<4>(mix.delayUp));
|
|
internalField.Append(new UnsignedField<4>(mix.delayDown));
|
|
internalField.Append(new UnsignedField<4>(mix.speedUp));
|
|
internalField.Append(new UnsignedField<4>(mix.speedDown));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
internalField.Append(new SignedField<8>(_offset));
|
|
}
|
|
else {
|
|
internalField.Append(new UnsignedField<4>(_destCh));
|
|
internalField.Append(new BoolField<1>(_curveMode));
|
|
internalField.Append(new BoolField<1>(mix.noExpo));
|
|
internalField.Append(new UnsignedField<1>(_weightMode));
|
|
internalField.Append(new UnsignedField<1>(_offsetMode));
|
|
internalField.Append(new SignedField<8>(_weight));
|
|
internalField.Append(new SwitchField<6>(mix.swtch, board, version));
|
|
internalField.Append(new UnsignedField<2>((unsigned int &)mix.mltpx));
|
|
internalField.Append(new UnsignedField<5>(mix.phases));
|
|
internalField.Append(new SignedField<3>(mix.carryTrim));
|
|
internalField.Append(new SourceField<6>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
|
|
internalField.Append(new UnsignedField<2>(mix.mixWarn));
|
|
internalField.Append(new UnsignedField<4>(mix.delayUp));
|
|
internalField.Append(new UnsignedField<4>(mix.delayDown));
|
|
internalField.Append(new UnsignedField<4>(mix.speedUp));
|
|
internalField.Append(new UnsignedField<4>(mix.speedDown));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
internalField.Append(new SignedField<8>(_offset));
|
|
}
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
if (mix.destCh && mix.srcRaw.type != SOURCE_TYPE_NONE) {
|
|
_destCh = mix.destCh - 1;
|
|
if (mix.curve.type == CurveReference::CURVE_REF_CUSTOM) {
|
|
_curveMode = true;
|
|
_curveParam = 6 + mix.curve.value;
|
|
}
|
|
else if (mix.curve.type == CurveReference::CURVE_REF_FUNC) {
|
|
_curveMode = true;
|
|
_curveParam = mix.curve.value;
|
|
}
|
|
else if (mix.curve.type == CurveReference::CURVE_REF_DIFF) {
|
|
_curveMode = 0;
|
|
_curveParam = smallGvarToEEPROM(mix.curve.value);
|
|
}
|
|
}
|
|
else {
|
|
mix.clear();
|
|
_destCh = 0;
|
|
_curveMode = 0;
|
|
_curveParam = 0;
|
|
}
|
|
|
|
if (IS_ARM(board)) {
|
|
exportGvarParam(mix.weight, _weight, version);
|
|
if (version >= 214)
|
|
exportGvarParam(mix.sOffset, _offset, version);
|
|
else
|
|
splitGvarParam(mix.sOffset, _offset, _offsetMode, board, version);
|
|
}
|
|
else {
|
|
splitGvarParam(mix.weight, _weight, _weightMode, board, version);
|
|
splitGvarParam(mix.sOffset, _offset, _offsetMode, board, version);
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
if (IS_TARANIS(board) && version < 216) {
|
|
if (mix.srcRaw.type == SOURCE_TYPE_STICK && mix.srcRaw.index < NUM_STICKS) {
|
|
if (!mix.noExpo) {
|
|
mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, mix.srcRaw.index, model);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mix.srcRaw.type != SOURCE_TYPE_NONE) {
|
|
mix.destCh = _destCh + 1;
|
|
if (!IS_ARM(board) || version < 216) {
|
|
if (!_curveMode)
|
|
mix.curve = CurveReference(CurveReference::CURVE_REF_DIFF, smallGvarToC9x(_curveParam));
|
|
else if (_curveParam > 6)
|
|
mix.curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, _curveParam-6);
|
|
else
|
|
mix.curve = CurveReference(CurveReference::CURVE_REF_FUNC, _curveParam);
|
|
}
|
|
}
|
|
|
|
if (IS_ARM(board)) {
|
|
importGvarParam(mix.weight, _weight, version);
|
|
if (version >= 214)
|
|
importGvarParam(mix.sOffset, _offset, version);
|
|
else
|
|
concatGvarParam(mix.sOffset, _offset, _offsetMode, board, version);
|
|
}
|
|
else {
|
|
concatGvarParam(mix.weight, _weight, _weightMode, board, version);
|
|
concatGvarParam(mix.sOffset, _offset, _offsetMode, board, version);
|
|
}
|
|
|
|
if (IS_TARANIS(board) && version < 216) {
|
|
if (mix.sOffset >= -500 && mix.sOffset <= 500 && mix.weight >= -500 && mix.weight <= 500) {
|
|
mix.sOffset = divRoundClosest(mix.sOffset * mix.weight, 100);
|
|
}
|
|
if (mix.carryTrim < 0) mix.carryTrim = 0;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
MixData & mix;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
ModelData * model;
|
|
unsigned int _destCh;
|
|
bool _curveMode;
|
|
int _curveParam;
|
|
int _weight;
|
|
int _offset;
|
|
unsigned int _weightMode;
|
|
unsigned int _offsetMode;
|
|
};
|
|
|
|
class InputField: public TransformedField {
|
|
public:
|
|
InputField(ExpoData & expo, BoardEnum board, unsigned int version):
|
|
TransformedField(internalField),
|
|
internalField("Input"),
|
|
expo(expo),
|
|
board(board),
|
|
version(version)
|
|
{
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
internalField.Append(new SourceField<8>(expo.srcRaw, board, version, 0));
|
|
internalField.Append(new UnsignedField<16>(expo.scale, "Scale"));
|
|
internalField.Append(new UnsignedField<8>(expo.chn, "Channel"));
|
|
internalField.Append(new SwitchField<8>(expo.swtch, board, version));
|
|
internalField.Append(new UnsignedField<16>(expo.phases));
|
|
internalField.Append(new SignedField<8>(_weight, "Weight"));
|
|
internalField.Append(new SignedField<6>(expo.carryTrim, "CarryTrim"));
|
|
internalField.Append(new UnsignedField<2>(expo.mode, "Mode"));
|
|
internalField.Append(new ZCharField<8>(expo.name));
|
|
internalField.Append(new SignedField<8>(expo.offset, "Offset"));
|
|
internalField.Append(new CurveReferenceField(expo.curve, board, version));
|
|
internalField.Append(new SpareBitsField<8>());
|
|
}
|
|
else if (IS_ARM(board) && version >= 216) {
|
|
internalField.Append(new UnsignedField<2>(expo.mode, "Mode"));
|
|
internalField.Append(new UnsignedField<4>(expo.chn, "Channel"));
|
|
internalField.Append(new BoolField<2>(_curveMode));
|
|
internalField.Append(new SwitchField<8>(expo.swtch, board, version));
|
|
internalField.Append(new UnsignedField<16>(expo.phases, "Phases"));
|
|
internalField.Append(new SignedField<8>(_weight, "Weight"));
|
|
internalField.Append(new ZCharField<6>(expo.name));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
}
|
|
else if (IS_ARM(board)) {
|
|
internalField.Append(new UnsignedField<8>(expo.mode, "Mode"));
|
|
internalField.Append(new UnsignedField<8>(expo.chn, "Channel"));
|
|
internalField.Append(new SwitchField<8>(expo.swtch, board, version));
|
|
internalField.Append(new UnsignedField<16>(expo.phases, "Phases"));
|
|
internalField.Append(new SignedField<8>(_weight, "Weight"));
|
|
internalField.Append(new BoolField<8>(_curveMode));
|
|
if (HAS_LARGE_LCD(board)) {
|
|
internalField.Append(new ZCharField<8>(expo.name));
|
|
internalField.Append(new SpareBitsField<16>());
|
|
}
|
|
else {
|
|
internalField.Append(new ZCharField<6>(expo.name));
|
|
}
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
}
|
|
else if (IS_DBLRAM(board, version) && IS_AFTER_RELEASE_23_MARCH_2013(board, version)) {
|
|
internalField.Append(new UnsignedField<2>(expo.mode));
|
|
internalField.Append(new UnsignedField<2>(expo.chn));
|
|
internalField.Append(new BoolField<1>(_curveMode));
|
|
internalField.Append(new SpareBitsField<3>());
|
|
internalField.Append(new UnsignedField<8>(expo.phases));
|
|
internalField.Append(new SwitchField<8>(expo.swtch, board, version));
|
|
internalField.Append(new SignedField<8>(_weight));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
}
|
|
else {
|
|
internalField.Append(new UnsignedField<2>(expo.mode));
|
|
internalField.Append(new SwitchField<6>(expo.swtch, board, version));
|
|
internalField.Append(new UnsignedField<2>(expo.chn));
|
|
internalField.Append(new UnsignedField<5>(expo.phases));
|
|
internalField.Append(new BoolField<1>(_curveMode));
|
|
internalField.Append(new SignedField<8>(_weight));
|
|
internalField.Append(new SignedField<8>(_curveParam));
|
|
}
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
_weight = smallGvarToEEPROM(expo.weight);
|
|
|
|
if (!IS_TARANIS(board) || version < 216) {
|
|
if (expo.curve.type==CurveReference::CURVE_REF_FUNC && expo.curve.value) {
|
|
_curveMode = true;
|
|
_curveParam = expo.curve.value;
|
|
}
|
|
else if (expo.curve.type==CurveReference::CURVE_REF_CUSTOM && expo.curve.value) {
|
|
_curveMode = true;
|
|
_curveParam = expo.curve.value+6;
|
|
}
|
|
else {
|
|
_curveMode = false;
|
|
_curveParam = smallGvarToEEPROM(expo.curve.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
if (IS_TARANIS(board)) {
|
|
if (version < 216) {
|
|
if (expo.mode) {
|
|
expo.srcRaw = RawSource(SOURCE_TYPE_STICK, expo.chn);
|
|
}
|
|
}
|
|
}
|
|
|
|
expo.weight = smallGvarToC9x(_weight);
|
|
|
|
if (!IS_TARANIS(board) || version < 216) {
|
|
if (!_curveMode)
|
|
expo.curve = CurveReference(CurveReference::CURVE_REF_EXPO, smallGvarToC9x(_curveParam));
|
|
else if (_curveParam > 6)
|
|
expo.curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, _curveParam-6);
|
|
else
|
|
expo.curve = CurveReference(CurveReference::CURVE_REF_FUNC, _curveParam);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
ExpoData & expo;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
bool _curveMode;
|
|
int _weight;
|
|
int _curveParam;
|
|
};
|
|
|
|
class LimitField: public StructField {
|
|
public:
|
|
LimitField(LimitData & limit, BoardEnum board, unsigned int version):
|
|
StructField("Limit")
|
|
{
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
Append(new ConversionField< SignedField<16> >(limit.min, +1000));
|
|
Append(new ConversionField< SignedField<16> >(limit.max, -1000));
|
|
}
|
|
else {
|
|
Append(new ConversionField< SignedField<8> >(limit.min, +100, 10));
|
|
Append(new ConversionField< SignedField<8> >(limit.max, -100, 10));
|
|
}
|
|
Append(new SignedField<8>(limit.ppmCenter));
|
|
Append(new SignedField<14>(limit.offset));
|
|
Append(new BoolField<1>(limit.symetrical));
|
|
Append(new BoolField<1>(limit.revert));
|
|
if (HAS_LARGE_LCD(board)) {
|
|
Append(new ZCharField<6>(limit.name));
|
|
}
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
Append(new SignedField<8>(limit.curve.value));
|
|
}
|
|
}
|
|
};
|
|
|
|
class CurvesField: public TransformedField {
|
|
public:
|
|
CurvesField(CurveData * curves, BoardEnum board, unsigned int version):
|
|
TransformedField(internalField),
|
|
internalField("Curves"),
|
|
curves(curves),
|
|
board(board),
|
|
version(version),
|
|
maxCurves(MAX_CURVES(board, version)),
|
|
maxPoints(IS_ARM(board) ? O9X_ARM_NUM_POINTS : O9X_NUM_POINTS)
|
|
{
|
|
for (int i=0; i<maxCurves; i++) {
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
internalField.Append(new UnsignedField<3>((unsigned int &)curves[i].type));
|
|
internalField.Append(new BoolField<1>(curves[i].smooth));
|
|
internalField.Append(new SpareBitsField<4>());
|
|
internalField.Append(new ConversionField< SignedField<8> >(curves[i].count, -5));
|
|
}
|
|
else if (IS_ARM(board)) {
|
|
internalField.Append(new SignedField<16>(_curves[i]));
|
|
}
|
|
else {
|
|
internalField.Append(new SignedField<8>(_curves[i]));
|
|
}
|
|
}
|
|
|
|
for (int i=0; i<maxPoints; i++) {
|
|
internalField.Append(new SignedField<8>(_points[i]));
|
|
}
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
memset(_points, 0, sizeof(_points));
|
|
|
|
int * cur = &_points[0];
|
|
int offset = 0;
|
|
|
|
for (int i=0; i<maxCurves; i++) {
|
|
CurveData *curve = &curves[i];
|
|
int size = (curve->type == CurveData::CURVE_TYPE_CUSTOM ? curve->count * 2 - 2 : curve->count);
|
|
if (offset+size > maxPoints) {
|
|
EEPROMWarnings += ::QObject::tr("OpenTX only accepts %1 points in all curves").arg(maxPoints) + "\n";
|
|
break;
|
|
}
|
|
if (!IS_TARANIS(board) || version < 216) {
|
|
_curves[i] = offset - (5*i);
|
|
}
|
|
for (int j=0; j<curve->count; j++) {
|
|
*cur++ = curve->points[j].y;
|
|
}
|
|
if (curve->type == CurveData::CURVE_TYPE_CUSTOM) {
|
|
for (int j=1; j<curve->count-1; j++) {
|
|
*cur++ = curve->points[j].x;
|
|
}
|
|
}
|
|
offset += size;
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
int * cur = &_points[0];
|
|
|
|
for (int i=0; i<maxCurves; i++) {
|
|
CurveData *curve = &curves[i];
|
|
if (!IS_TARANIS(board) || version < 216) {
|
|
int * next = &_points[5*(i+1) + _curves[i]];
|
|
int size = next - cur;
|
|
if (size % 2 == 0) {
|
|
curve->count = (size / 2) + 1;
|
|
curve->type = CurveData::CURVE_TYPE_CUSTOM;
|
|
}
|
|
else {
|
|
curve->count = size;
|
|
curve->type = CurveData::CURVE_TYPE_STANDARD;
|
|
}
|
|
}
|
|
|
|
if (curve->count > 17) {
|
|
qDebug() << "Wrong points count" << curve->count;
|
|
curve->count = 0;
|
|
for (int j=0; j<maxCurves; j++) {
|
|
CurveData *curve = &curves[j];
|
|
curve->clear(5);
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (int j=0; j<curve->count; j++) {
|
|
curve->points[j].y = *cur++;
|
|
}
|
|
|
|
if (curve->type == CurveData::CURVE_TYPE_CUSTOM) {
|
|
curve->points[0].x = -100;
|
|
for (int j=1; j<curve->count-1; j++)
|
|
curve->points[j].x = *cur++;
|
|
curve->points[curve->count-1].x = +100;
|
|
}
|
|
else {
|
|
for (int j=0; j<curve->count; j++)
|
|
curve->points[j].x = -100 + (200*i) / (curve->count-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
CurveData *curves;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
int maxCurves;
|
|
int maxPoints;
|
|
int _curves[C9X_MAX_CURVES];
|
|
int _points[C9X_MAX_CURVES*C9X_MAX_POINTS*2];
|
|
};
|
|
|
|
class LogicalSwitchesFunctionsTable: public ConversionTable {
|
|
|
|
public:
|
|
LogicalSwitchesFunctionsTable(BoardEnum board, unsigned int version)
|
|
{
|
|
int val=0;
|
|
bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version);
|
|
addConversion(LS_FN_OFF, val++);
|
|
if (IS_ARM(board) && version >= 216)
|
|
addConversion(LS_FN_VEQUAL, val++);
|
|
if (afterrelease21March2013)
|
|
addConversion(LS_FN_VALMOSTEQUAL, val++);
|
|
addConversion(LS_FN_VPOS, val++);
|
|
addConversion(LS_FN_VNEG, val++);
|
|
if (IS_ARM(board) && version >= 216) val++; // later RANGE
|
|
addConversion(LS_FN_APOS, val++);
|
|
addConversion(LS_FN_ANEG, val++);
|
|
addConversion(LS_FN_AND, val++);
|
|
addConversion(LS_FN_OR, val++);
|
|
addConversion(LS_FN_XOR, val++);
|
|
if (IS_ARM(board) && version >= 216) addConversion(LS_FN_STAY, val++);
|
|
addConversion(LS_FN_EQUAL, val++);
|
|
if (!afterrelease21March2013)
|
|
addConversion(LS_FN_NEQUAL, val++);
|
|
addConversion(LS_FN_GREATER, val++);
|
|
addConversion(LS_FN_LESS, val++);
|
|
if (!afterrelease21March2013) {
|
|
addConversion(LS_FN_EGREATER, val++);
|
|
addConversion(LS_FN_ELESS, val++);
|
|
}
|
|
addConversion(LS_FN_DPOS, val++);
|
|
addConversion(LS_FN_DAPOS, val++);
|
|
addConversion(LS_FN_TIMER, val++);
|
|
if (version >= 216)
|
|
addConversion(LS_FN_STICKY, val++);
|
|
}
|
|
};
|
|
|
|
class AndSwitchesConversionTable: public ConversionTable {
|
|
|
|
public:
|
|
AndSwitchesConversionTable(BoardEnum board, unsigned int version)
|
|
{
|
|
int val=0;
|
|
addConversion(RawSwitch(SWITCH_TYPE_NONE), val++);
|
|
|
|
if (IS_TARANIS(board)) {
|
|
for (int i=1; i<=MAX_SWITCHES_POSITION(board); i++) {
|
|
int s = switchIndex(i, board, version);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, -s), -val);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, s), val++);
|
|
}
|
|
for (int i=1; i<=MAX_CUSTOM_SWITCHES(board, version); i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, -i), -val);
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, i), val++);
|
|
}
|
|
}
|
|
else if (board == BOARD_SKY9X) {
|
|
for (int i=1; i<=8; i++) {
|
|
int s = switchIndex(i, board, version);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, -s), -val);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, s), val++);
|
|
}
|
|
for (int i=1; i<=MAX_CUSTOM_SWITCHES(board, version); i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, -i), -val);
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, i), val++);
|
|
}
|
|
}
|
|
else {
|
|
for (int i=1; i<=9; i++) {
|
|
int s = switchIndex(i, board, version);
|
|
addConversion(RawSwitch(SWITCH_TYPE_SWITCH, s), val++);
|
|
}
|
|
for (int i=1; i<=7; i++) {
|
|
addConversion(RawSwitch(SWITCH_TYPE_VIRTUAL, i), val++);
|
|
}
|
|
}
|
|
}
|
|
|
|
static ConversionTable * getInstance(BoardEnum board, unsigned int version)
|
|
{
|
|
if (IS_ARM(board) && version >= 216)
|
|
return new SwitchesConversionTable(board, version);
|
|
else
|
|
return new AndSwitchesConversionTable(board, version);
|
|
|
|
#if 0
|
|
static std::list<Cache> internalCache;
|
|
|
|
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
|
|
Cache element = *it;
|
|
if (element.board == board && element.version == version && element.flags == flags)
|
|
return element.table;
|
|
}
|
|
|
|
Cache element(board, version, flags, new SwitchesConversionTable(board, version, flags));
|
|
internalCache.push_back(element);
|
|
return element.table;
|
|
#endif
|
|
}
|
|
|
|
|
|
protected:
|
|
|
|
void addConversion(const RawSwitch & sw, const int b)
|
|
{
|
|
ConversionTable::addConversion(sw.toValue(), b);
|
|
}
|
|
};
|
|
|
|
class LogicalSwitchField: public TransformedField {
|
|
public:
|
|
LogicalSwitchField(LogicalSwitchData & csw, BoardEnum board, unsigned int version, unsigned int variant, ModelData * model=NULL):
|
|
TransformedField(internalField),
|
|
internalField("LogicalSwitch"),
|
|
csw(csw),
|
|
board(board),
|
|
version(version),
|
|
variant(variant),
|
|
model(model),
|
|
functionsConversionTable(board, version),
|
|
sourcesConversionTable(SourcesConversionTable::getInstance(board, version, variant, (version >= 214 || (!IS_ARM(board) && version >= 213)) ? 0 : FLAG_NOSWITCHES)),
|
|
switchesConversionTable(SwitchesConversionTable::getInstance(board, version)),
|
|
andswitchesConversionTable(AndSwitchesConversionTable::getInstance(board, version)),
|
|
v1(0),
|
|
v2(0),
|
|
v3(0)
|
|
{
|
|
if (IS_ARM(board) && version >= 216) {
|
|
internalField.Append(new SignedField<8>(v1));
|
|
internalField.Append(new SignedField<16>(v2));
|
|
internalField.Append(new SignedField<16>(v3));
|
|
}
|
|
else if (IS_ARM(board) && version >= 215) {
|
|
internalField.Append(new SignedField<16>(v1));
|
|
internalField.Append(new SignedField<16>(v2));
|
|
}
|
|
else {
|
|
internalField.Append(new SignedField<8>(v1));
|
|
internalField.Append(new SignedField<8>(v2));
|
|
}
|
|
|
|
if (IS_ARM(board)) {
|
|
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
|
|
int scale = (version >= 216 ? 0 : 5);
|
|
internalField.Append(new ConversionField< UnsignedField<8> >(csw.delay, 0, scale));
|
|
internalField.Append(new ConversionField< UnsignedField<8> >(csw.duration, 0, scale));
|
|
if (version >= 214) {
|
|
internalField.Append(new ConversionField< SignedField<8> >((int &)csw.andsw, andswitchesConversionTable, "AND switch"));
|
|
}
|
|
}
|
|
else {
|
|
if (version >= 213) {
|
|
internalField.Append(new ConversionField< UnsignedField<4> >(csw.func, &functionsConversionTable, "Function"));
|
|
internalField.Append(new ConversionField< UnsignedField<4> >((unsigned int &)csw.andsw, andswitchesConversionTable, "AND switch"));
|
|
}
|
|
else {
|
|
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
|
|
}
|
|
}
|
|
}
|
|
|
|
~LogicalSwitchField()
|
|
{
|
|
delete andswitchesConversionTable;
|
|
}
|
|
virtual void beforeExport()
|
|
{
|
|
if (csw.func == LS_FN_TIMER) {
|
|
v1 = csw.val1;
|
|
v2 = csw.val2;
|
|
}
|
|
else if (csw.func == LS_FN_STAY) {
|
|
switchesConversionTable->exportValue(csw.val1, v1);
|
|
v2 = csw.val2;
|
|
v3 = csw.val3;
|
|
}
|
|
else if ((csw.func >= LS_FN_AND && csw.func <= LS_FN_XOR) || csw.func == LS_FN_STICKY) {
|
|
switchesConversionTable->exportValue(csw.val1, v1);
|
|
switchesConversionTable->exportValue(csw.val2, v2);
|
|
}
|
|
else if (csw.func >= LS_FN_EQUAL && csw.func <= LS_FN_ELESS) {
|
|
sourcesConversionTable->exportValue(csw.val1, v1);
|
|
sourcesConversionTable->exportValue(csw.val2, v2);
|
|
}
|
|
else if (csw.func != LS_FN_OFF) {
|
|
sourcesConversionTable->exportValue(csw.val1, v1);
|
|
v2 = csw.val2;
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
if (csw.func == LS_FN_TIMER) {
|
|
csw.val1 = v1;
|
|
csw.val2 = v2;
|
|
}
|
|
else if (csw.func == LS_FN_STAY) {
|
|
switchesConversionTable->importValue(v1, csw.val1);
|
|
csw.val2 = v2;
|
|
csw.val3 = v3;
|
|
}
|
|
else if ((csw.func >= LS_FN_AND && csw.func <= LS_FN_XOR) || csw.func == LS_FN_STICKY) {
|
|
switchesConversionTable->importValue(v1, csw.val1);
|
|
switchesConversionTable->importValue(v2, csw.val2);
|
|
}
|
|
else if (csw.func >= LS_FN_EQUAL && csw.func <= LS_FN_ELESS) {
|
|
sourcesConversionTable->importValue((uint8_t)v1, csw.val1);
|
|
sourcesConversionTable->importValue((uint8_t)v2, csw.val2);
|
|
}
|
|
else if (csw.func != LS_FN_OFF) {
|
|
sourcesConversionTable->importValue((uint8_t)v1, csw.val1);
|
|
csw.val2 = v2;
|
|
RawSource val1(csw.val1, model);
|
|
if (IS_ARM(board) && version < 216 && val1.type == SOURCE_TYPE_TELEMETRY) {
|
|
switch (val1.index) {
|
|
case TELEMETRY_SOURCE_TIMER1:
|
|
case TELEMETRY_SOURCE_TIMER2:
|
|
csw.val2 = (csw.val2 + 128) * 3;
|
|
break;
|
|
case TELEMETRY_SOURCE_ALT:
|
|
case TELEMETRY_SOURCE_GPS_ALT:
|
|
case TELEMETRY_SOURCE_ALT_MIN:
|
|
case TELEMETRY_SOURCE_ALT_MAX:
|
|
csw.val2 = (csw.val2 + 128) * 8 - 500;
|
|
break;
|
|
case TELEMETRY_SOURCE_RPM:
|
|
case TELEMETRY_SOURCE_RPM_MAX:
|
|
csw.val2 = (csw.val2 + 128) * 50;
|
|
break;
|
|
case TELEMETRY_SOURCE_T1:
|
|
case TELEMETRY_SOURCE_T2:
|
|
case TELEMETRY_SOURCE_T1_MAX:
|
|
case TELEMETRY_SOURCE_T2_MAX:
|
|
csw.val2 = (csw.val2 + 128) + 30;
|
|
break;
|
|
case TELEMETRY_SOURCE_CELL:
|
|
case TELEMETRY_SOURCE_HDG:
|
|
csw.val2 = (csw.val2 + 128) * 2;
|
|
break;
|
|
case TELEMETRY_SOURCE_DIST:
|
|
case TELEMETRY_SOURCE_DIST_MAX:
|
|
csw.val2 = (csw.val2 + 128) * 8;
|
|
break;
|
|
case TELEMETRY_SOURCE_CURRENT:
|
|
case TELEMETRY_SOURCE_POWER:
|
|
csw.val2 = (csw.val2 + 128) * 5;
|
|
break;
|
|
case TELEMETRY_SOURCE_CONSUMPTION:
|
|
csw.val2 = (csw.val2 + 128) * 20;
|
|
break;
|
|
default:
|
|
csw.val2 += 128;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
LogicalSwitchData & csw;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
unsigned int variant;
|
|
ModelData * model;
|
|
LogicalSwitchesFunctionsTable functionsConversionTable;
|
|
SourcesConversionTable * sourcesConversionTable;
|
|
SwitchesConversionTable * switchesConversionTable;
|
|
ConversionTable * andswitchesConversionTable;
|
|
int v1;
|
|
int v2;
|
|
int v3;
|
|
};
|
|
|
|
class CustomFunctionsConversionTable: public ConversionTable {
|
|
|
|
public:
|
|
CustomFunctionsConversionTable(BoardEnum board, unsigned int version)
|
|
{
|
|
int val=0;
|
|
|
|
if (version >= 216) {
|
|
for (int i=0; i<32; i++) {
|
|
addConversion(i, val);
|
|
}
|
|
val++;
|
|
}
|
|
else if (IS_ARM(board) || version < 213) {
|
|
for (int i=0; i<16; i++) {
|
|
addConversion(val, val);
|
|
val++;
|
|
}
|
|
}
|
|
else {
|
|
for (int i=0; i<16; i++) {
|
|
addConversion(i, i / 4);
|
|
}
|
|
val+=4;
|
|
}
|
|
|
|
if (version >= 216) {
|
|
addConversion(FuncTrainer, val);
|
|
addConversion(FuncTrainerRUD, val);
|
|
addConversion(FuncTrainerELE, val);
|
|
addConversion(FuncTrainerTHR, val);
|
|
addConversion(FuncTrainerAIL, val);
|
|
val++;
|
|
}
|
|
else {
|
|
addConversion(FuncTrainer, val++);
|
|
addConversion(FuncTrainerRUD, val++);
|
|
addConversion(FuncTrainerELE, val++);
|
|
addConversion(FuncTrainerTHR, val++);
|
|
addConversion(FuncTrainerAIL, val++);
|
|
}
|
|
|
|
addConversion(FuncInstantTrim, val++);
|
|
|
|
if (version >= 216) {
|
|
addConversion(FuncReset, val++);
|
|
if (IS_ARM(board)) {
|
|
addConversion(FuncSetTimer1, val);
|
|
addConversion(FuncSetTimer2, val);
|
|
val++;
|
|
}
|
|
for (int i=0; i<MAX_GVARS(board, version); i++)
|
|
addConversion(FuncAdjustGV1+i, val);
|
|
val++;
|
|
if (IS_ARM(board)) {
|
|
addConversion(FuncVolume, val++);
|
|
addConversion(FuncReserve, val++);
|
|
addConversion(FuncReserve, val++);
|
|
addConversion(FuncReserve, val++);
|
|
}
|
|
addConversion(FuncPlaySound, val++);
|
|
addConversion(FuncPlayPrompt, val++);
|
|
if (version >= 213 && !IS_ARM(board))
|
|
addConversion(FuncPlayBoth, val++);
|
|
addConversion(FuncPlayValue, val++);
|
|
if (IS_ARM(board)) {
|
|
addConversion(FuncReserve, val++);
|
|
addConversion(FuncReserve, val++);
|
|
addConversion(FuncReserve, val++);
|
|
addConversion(FuncBackgroundMusic, val++);
|
|
addConversion(FuncBackgroundMusicPause, val++);
|
|
}
|
|
addConversion(FuncVario, val++);
|
|
addConversion(FuncPlayHaptic, val++);
|
|
if (board == BOARD_GRUVIN9X || IS_ARM(board) )
|
|
addConversion(FuncLogs, val++);
|
|
addConversion(FuncBacklight, val++);
|
|
}
|
|
else {
|
|
addConversion(FuncPlaySound, val++);
|
|
if (!IS_TARANIS(board))
|
|
addConversion(FuncPlayHaptic, val++);
|
|
addConversion(FuncReset, val++);
|
|
addConversion(FuncVario, val++);
|
|
addConversion(FuncPlayPrompt, val++);
|
|
if (version >= 213 && !IS_ARM(board))
|
|
addConversion(FuncPlayBoth, val++);
|
|
addConversion(FuncPlayValue, val++);
|
|
if (board == BOARD_GRUVIN9X || IS_ARM(board) )
|
|
addConversion(FuncLogs, val++);
|
|
if (IS_ARM(board))
|
|
addConversion(FuncVolume, val++);
|
|
addConversion(FuncBacklight, val++);
|
|
if (IS_ARM(board)) {
|
|
addConversion(FuncBackgroundMusic, val++);
|
|
addConversion(FuncBackgroundMusicPause, val++);
|
|
}
|
|
for (int i=0; i<5; i++)
|
|
addConversion(FuncAdjustGV1+i, val++);
|
|
}
|
|
}
|
|
};
|
|
|
|
template <int N>
|
|
class SwitchesWarningField: public TransformedField {
|
|
public:
|
|
SwitchesWarningField(unsigned int & sw, BoardEnum board, unsigned int version):
|
|
TransformedField(internalField),
|
|
internalField(_sw, "SwitchesWarning"),
|
|
sw(sw),
|
|
board(board),
|
|
version(version)
|
|
{
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
_sw = sw;
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version);
|
|
if (afterrelease21March2013 && version < 216) {
|
|
sw = _sw >> 1;
|
|
}
|
|
else if (!afterrelease21March2013) {
|
|
sw = ((_sw & 0x30) >> 4) + ((_sw & 0x0E) << 1) + ((_sw & 0xC0) >> 1);
|
|
}
|
|
else {
|
|
sw = _sw;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
UnsignedField<N> internalField;
|
|
unsigned int &sw;
|
|
unsigned int _sw;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
};
|
|
|
|
class ArmCustomFunctionField: public TransformedField {
|
|
public:
|
|
ArmCustomFunctionField(FuncSwData & fn, BoardEnum board, unsigned int version, unsigned int variant):
|
|
TransformedField(internalField),
|
|
internalField("CustomFunction"),
|
|
fn(fn),
|
|
board(board),
|
|
version(version),
|
|
variant(variant),
|
|
functionsConversionTable(board, version),
|
|
sourcesConversionTable(SourcesConversionTable::getInstance(board, version, variant, version >= 216 ? 0 : FLAG_NONONE)),
|
|
_active(0)
|
|
{
|
|
memset(_param, 0, sizeof(_param));
|
|
|
|
internalField.Append(new SwitchField<8>(fn.swtch, board, version));
|
|
internalField.Append(new ConversionField< UnsignedField<8> >((unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
|
|
|
|
if (IS_TARANIS(board) && version >= 216)
|
|
internalField.Append(new CharField<8>(_param, false));
|
|
else if (IS_TARANIS(board))
|
|
internalField.Append(new CharField<10>(_param, false));
|
|
else
|
|
internalField.Append(new CharField<6>(_param, false));
|
|
|
|
if (version >= 216) {
|
|
internalField.Append(new UnsignedField<8>(_active));
|
|
}
|
|
else if (version >= 214) {
|
|
internalField.Append(new UnsignedField<2>(_mode));
|
|
internalField.Append(new UnsignedField<6>(_active));
|
|
}
|
|
else {
|
|
internalField.Append(new UnsignedField<8>((unsigned int &)_active));
|
|
internalField.Append(new SpareBitsField<8>());
|
|
}
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
_mode = 0;
|
|
|
|
if (fn.func == FuncPlaySound || fn.func == FuncPlayPrompt || fn.func == FuncPlayValue)
|
|
_active = (version >= 216 ? fn.repeatParam : (fn.repeatParam/5));
|
|
else
|
|
_active = (fn.enabled ? 1 : 0);
|
|
|
|
if (fn.func >= FuncSafetyCh1 && fn.func <= FuncSafetyCh32) {
|
|
if (version >= 216) {
|
|
*((uint16_t *)_param) = fn.param;
|
|
*((uint8_t *)(_param+3)) = fn.func - FuncSafetyCh1;
|
|
}
|
|
else {
|
|
*((uint32_t *)_param) = fn.param;
|
|
}
|
|
}
|
|
else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerAIL) {
|
|
if (version >= 216)
|
|
*((uint8_t *)(_param+3)) = fn.func - FuncTrainer;
|
|
}
|
|
else if (fn.func >= FuncSetTimer1 && fn.func <= FuncSetTimer2) {
|
|
if (version >= 216) {
|
|
*((uint16_t *)_param) = fn.param;
|
|
*((uint8_t *)(_param+3)) = fn.func - FuncSetTimer1;
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlayPrompt || fn.func == FuncBackgroundMusic) {
|
|
memcpy(_param, fn.paramarm, sizeof(_param));
|
|
}
|
|
else if (fn.func >= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast) {
|
|
if (version >= 216) {
|
|
*((uint8_t *)(_param+2)) = fn.adjustMode;
|
|
*((uint8_t *)(_param+3)) = fn.func - FuncAdjustGV1;
|
|
unsigned int value;
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->exportValue(fn.param, (int &)value);
|
|
else if (fn.adjustMode == 2)
|
|
value = RawSource(fn.param).index;
|
|
else
|
|
value = fn.param;
|
|
*((uint16_t *)_param) = value;
|
|
}
|
|
else if (version >= 214) {
|
|
unsigned int value;
|
|
_mode = fn.adjustMode;
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->exportValue(fn.param, (int &)value);
|
|
else if (fn.adjustMode == 2)
|
|
value = RawSource(fn.param).index;
|
|
else
|
|
value = fn.param;
|
|
*((uint32_t *)_param) = value;
|
|
}
|
|
else {
|
|
unsigned int value;
|
|
sourcesConversionTable->exportValue(fn.param, (int &)value);
|
|
*((uint32_t *)_param) = value;
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlayValue || fn.func == FuncVolume) {
|
|
unsigned int value;
|
|
sourcesConversionTable->exportValue(fn.param, (int &)value);
|
|
if (version >= 216)
|
|
*((uint16_t *)_param) = value;
|
|
else
|
|
*((uint32_t *)_param) = value;
|
|
}
|
|
else {
|
|
*((uint32_t *)_param) = fn.param;
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
if (fn.func == FuncPlaySound || fn.func == FuncPlayPrompt || fn.func == FuncPlayValue)
|
|
fn.repeatParam = (version >= 216 ? _active : (_active*5));
|
|
else
|
|
fn.enabled = (_active & 0x01);
|
|
|
|
unsigned int value=0, mode=0, index=0;
|
|
if (version >= 216) {
|
|
value = *((uint16_t *)_param);
|
|
mode = *((uint8_t *)(_param+2));
|
|
index = *((uint8_t *)(_param+3));
|
|
}
|
|
else {
|
|
value = *((uint32_t *)_param);
|
|
}
|
|
|
|
if (fn.func >= FuncSafetyCh1 && fn.func <= FuncSafetyCh32) {
|
|
fn.func = AssignFunc(fn.func + index);
|
|
fn.param = (int8_t)value;
|
|
}
|
|
else if (fn.func >= FuncSetTimer1 && fn.func <= FuncSetTimer2) {
|
|
fn.func = AssignFunc(fn.func + index);
|
|
fn.param = (int)value;
|
|
}
|
|
else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerAIL) {
|
|
fn.func = AssignFunc(fn.func + index);
|
|
fn.param = value;
|
|
}
|
|
else if (fn.func == FuncPlayPrompt || fn.func == FuncBackgroundMusic) {
|
|
memcpy(fn.paramarm, _param, sizeof(fn.paramarm));
|
|
}
|
|
else if (fn.func == FuncVolume) {
|
|
sourcesConversionTable->importValue(value, (int &)fn.param);
|
|
}
|
|
else if (fn.func >= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast) {
|
|
if (version >= 216) {
|
|
fn.func = AssignFunc(fn.func + index);
|
|
fn.adjustMode = mode;
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->importValue(value, (int &)fn.param);
|
|
else if (fn.adjustMode == 2)
|
|
fn.param = RawSource(SOURCE_TYPE_GVAR, value).toValue();
|
|
else
|
|
fn.param = value;
|
|
}
|
|
else if (version >= 214) {
|
|
fn.adjustMode = _mode;
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->importValue(value, (int &)fn.param);
|
|
else if (fn.adjustMode == 2)
|
|
fn.param = RawSource(SOURCE_TYPE_GVAR, value).toValue();
|
|
else
|
|
fn.param = value;
|
|
}
|
|
else {
|
|
sourcesConversionTable->importValue(value, (int &)fn.param);
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlayValue) {
|
|
if (version >= 213)
|
|
sourcesConversionTable->importValue(value, (int &)fn.param);
|
|
else
|
|
SourcesConversionTable::getInstance(board, version, variant, FLAG_NONONE|FLAG_NOSWITCHES)->importValue(value, (int &)fn.param);
|
|
}
|
|
else {
|
|
fn.param = value;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
FuncSwData & fn;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
unsigned int variant;
|
|
CustomFunctionsConversionTable functionsConversionTable;
|
|
SourcesConversionTable * sourcesConversionTable;
|
|
char _param[10];
|
|
unsigned int _active;
|
|
unsigned int _mode;
|
|
};
|
|
|
|
class AvrCustomFunctionField: public TransformedField {
|
|
public:
|
|
AvrCustomFunctionField(FuncSwData & fn, BoardEnum board, unsigned int version, unsigned int variant):
|
|
TransformedField(internalField),
|
|
internalField("CustomFunction"),
|
|
fn(fn),
|
|
board(board),
|
|
version(version),
|
|
variant(variant),
|
|
functionsConversionTable(board, version),
|
|
sourcesConversionTable(SourcesConversionTable::getInstance(board, version, variant, version >= 216 ? 0 : FLAG_NONONE)),
|
|
_param(0),
|
|
_union_param(0),
|
|
_active(0)
|
|
{
|
|
if (version >= 216) {
|
|
internalField.Append(new SwitchField<6>(fn.swtch, board, version));
|
|
internalField.Append(new ConversionField< UnsignedField<4> >((unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
|
|
internalField.Append(new UnsignedField<5>(_union_param));
|
|
internalField.Append(new UnsignedField<1>(_active));
|
|
}
|
|
else if (version >= 213) {
|
|
internalField.Append(new SwitchField<8>(fn.swtch, board, version));
|
|
internalField.Append(new UnsignedField<3>(_union_param));
|
|
internalField.Append(new ConversionField< UnsignedField<5> >((unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
|
|
}
|
|
else {
|
|
internalField.Append(new SwitchField<8>(fn.swtch, board, version));
|
|
internalField.Append(new ConversionField< UnsignedField<7> >((unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
|
|
internalField.Append(new BoolField<1>((bool &)fn.enabled));
|
|
}
|
|
internalField.Append(new UnsignedField<8>(_param));
|
|
}
|
|
|
|
virtual void beforeExport()
|
|
{
|
|
_param = fn.param;
|
|
_active = (fn.enabled ? 1 : 0);
|
|
|
|
if (fn.func >= FuncSafetyCh1 && fn.func <= FuncSafetyCh32) {
|
|
if (version >= 216)
|
|
_union_param = fn.func - FuncSafetyCh1;
|
|
else if (version >= 213)
|
|
_active += ((fn.func % 4) << 1);
|
|
}
|
|
else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerAIL) {
|
|
if (version >= 216)
|
|
_union_param = fn.func - FuncTrainer;
|
|
}
|
|
else if (fn.func >= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast) {
|
|
if (version >= 216) {
|
|
_union_param = fn.adjustMode;
|
|
_union_param += (fn.func - FuncAdjustGV1) << 2;
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->exportValue(fn.param, (int &)_param);
|
|
else if (fn.adjustMode == 2)
|
|
_param = RawSource(fn.param).index;
|
|
}
|
|
else if (version >= 213) {
|
|
_active += (fn.adjustMode << 1);
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->exportValue(fn.param, (int &)_param);
|
|
else if (fn.adjustMode == 2)
|
|
_param = RawSource(fn.param).index;
|
|
}
|
|
else {
|
|
sourcesConversionTable->exportValue(fn.param, (int &)_param);
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlayValue) {
|
|
if (version >= 216) {
|
|
_union_param = fn.repeatParam / 10;
|
|
sourcesConversionTable->exportValue(fn.param, (int &)_param);
|
|
}
|
|
else if (version >= 213) {
|
|
_active = fn.repeatParam / 10;
|
|
sourcesConversionTable->exportValue(fn.param, (int &)_param);
|
|
}
|
|
else {
|
|
SourcesConversionTable::getInstance(board, version, variant, FLAG_NONONE|FLAG_NOSWITCHES)->exportValue(fn.param, (int &)_param);
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlaySound || fn.func == FuncPlayPrompt || fn.func == FuncPlayBoth) {
|
|
if (version >= 216) {
|
|
_union_param = fn.repeatParam / 10;
|
|
}
|
|
else if (version >= 213) {
|
|
_active = fn.repeatParam / 10;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void afterImport()
|
|
{
|
|
fn.param = _param;
|
|
if (version >= 213) {
|
|
fn.enabled = (_active & 0x01);
|
|
}
|
|
|
|
if (fn.func >= FuncSafetyCh1 && fn.func <= FuncSafetyCh32) {
|
|
if (version >= 216)
|
|
fn.func = AssignFunc(fn.func + _union_param);
|
|
else if (version >= 213)
|
|
fn.func = AssignFunc(((fn.func >> 2) << 2) + ((_active >> 1) & 0x03));
|
|
fn.param = (int8_t)fn.param;
|
|
}
|
|
else if (fn.func >= FuncTrainer && fn.func <= FuncTrainerAIL) {
|
|
if (version >= 216)
|
|
fn.func = AssignFunc(fn.func + _union_param);
|
|
}
|
|
else if (fn.func >= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast) {
|
|
if (version >= 216) {
|
|
fn.func = AssignFunc(fn.func + (_union_param >> 2));
|
|
fn.adjustMode = (_union_param & 0x03);
|
|
}
|
|
else if (version >= 213) {
|
|
fn.adjustMode = ((_active >> 1) & 0x03);
|
|
if (fn.adjustMode == 1)
|
|
sourcesConversionTable->importValue(_param, (int &)fn.param);
|
|
else if (fn.adjustMode == 2)
|
|
fn.param = RawSource(SOURCE_TYPE_GVAR, _param).toValue();
|
|
}
|
|
else {
|
|
sourcesConversionTable->importValue(_param, (int &)fn.param);
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlayValue) {
|
|
if (version >= 216) {
|
|
fn.repeatParam = _union_param * 10;
|
|
sourcesConversionTable->importValue(_param, (int &)fn.param);
|
|
}
|
|
else if (version >= 213) {
|
|
fn.repeatParam = _active * 10;
|
|
sourcesConversionTable->importValue(_param, (int &)fn.param);
|
|
}
|
|
else {
|
|
SourcesConversionTable::getInstance(board, version, variant, FLAG_NONONE|FLAG_NOSWITCHES)->importValue(_param, (int &)fn.param);
|
|
}
|
|
}
|
|
else if (fn.func == FuncPlaySound || fn.func == FuncPlayPrompt || fn.func == FuncPlayBoth) {
|
|
if (version >= 216)
|
|
fn.repeatParam = _union_param * 10;
|
|
else if (version >= 213)
|
|
fn.repeatParam = _active * 10;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
StructField internalField;
|
|
FuncSwData & fn;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
unsigned int variant;
|
|
CustomFunctionsConversionTable functionsConversionTable;
|
|
SourcesConversionTable * sourcesConversionTable;
|
|
unsigned int _param;
|
|
unsigned int _mode;
|
|
unsigned int _union_param;
|
|
unsigned int _active;
|
|
};
|
|
|
|
class FrskyScreenField: public DataField {
|
|
public:
|
|
FrskyScreenField(FrSkyScreenData & screen, BoardEnum board, unsigned int version):
|
|
DataField("Frsky Screen"),
|
|
screen(screen),
|
|
board(board),
|
|
version(version)
|
|
{
|
|
for (int i=0; i<4; i++) {
|
|
bars.Append(new TelemetrySourceField<8>(screen.body.bars[i].source, board, version));
|
|
bars.Append(new UnsignedField<8>(screen.body.bars[i].barMin));
|
|
bars.Append(new UnsignedField<8>(screen.body.bars[i].barMax));
|
|
}
|
|
|
|
int columns=(IS_TARANIS(board) ? 3:2);
|
|
for (int i=0; i<4; i++) {
|
|
for (int j=0; j<columns; j++) {
|
|
numbers.Append(new TelemetrySourceField<8>(screen.body.lines[i].source[j], board, version));
|
|
}
|
|
}
|
|
if (!IS_TARANIS(board)) {
|
|
for (int i=0; i<4; i++) {
|
|
numbers.Append(new SpareBitsField<8>());
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void ExportBits(QBitArray & output)
|
|
{
|
|
if (screen.type == 0)
|
|
numbers.ExportBits(output);
|
|
else
|
|
bars.ExportBits(output);
|
|
}
|
|
|
|
virtual void ImportBits(QBitArray & input)
|
|
{
|
|
// NOTA: screen.type should have been imported first!
|
|
if (screen.type == 0) {
|
|
numbers.ImportBits(input);
|
|
}
|
|
else {
|
|
bars.ImportBits(input);
|
|
}
|
|
|
|
}
|
|
|
|
virtual unsigned int size()
|
|
{
|
|
// NOTA: screen.type should have been imported first!
|
|
if (screen.type == 0)
|
|
return numbers.size();
|
|
else
|
|
return bars.size();
|
|
}
|
|
|
|
protected:
|
|
FrSkyScreenData & screen;
|
|
BoardEnum board;
|
|
unsigned int version;
|
|
StructField bars;
|
|
StructField numbers;
|
|
};
|
|
|
|
class RSSIConversionTable: public ConversionTable
|
|
{
|
|
public:
|
|
RSSIConversionTable(int index)
|
|
{
|
|
addConversion(0, 2-index);
|
|
addConversion(1, 3-index);
|
|
addConversion(2, index ? 3 : 0);
|
|
addConversion(3, 1-index);
|
|
}
|
|
|
|
RSSIConversionTable()
|
|
{
|
|
}
|
|
};
|
|
|
|
class VarioConversionTable: public ConversionTable
|
|
{
|
|
public:
|
|
VarioConversionTable()
|
|
{
|
|
addConversion(2, 0); // Vario
|
|
addConversion(3, 1); // A1
|
|
addConversion(4, 2); // A2
|
|
}
|
|
};
|
|
|
|
class FrskyField: public StructField {
|
|
public:
|
|
FrskyField(FrSkyData & frsky, BoardEnum board, unsigned int version):
|
|
StructField("FrSky")
|
|
{
|
|
rssiConversionTable[0] = RSSIConversionTable(0);
|
|
rssiConversionTable[1] = RSSIConversionTable(1);
|
|
|
|
if (IS_ARM(board)) {
|
|
for (int i=0; i<2; i++) {
|
|
Append(new UnsignedField<8>(frsky.channels[i].ratio, "Ratio"));
|
|
Append(new SignedField<12>(frsky.channels[i].offset, "Offset"));
|
|
Append(new UnsignedField<4>(frsky.channels[i].type, "Type"));
|
|
for (int j=0; j<2; j++)
|
|
Append(new UnsignedField<8>(frsky.channels[i].alarms[j].value, "Alarm value"));
|
|
for (int j=0; j<2; j++)
|
|
Append(new UnsignedField<2>(frsky.channels[i].alarms[j].level));
|
|
for (int j=0; j<2; j++)
|
|
Append(new UnsignedField<1>(frsky.channels[i].alarms[j].greater));
|
|
Append(new SpareBitsField<2>());
|
|
Append(new UnsignedField<8>(frsky.channels[i].multiplier, 0, 5, "Multiplier"));
|
|
}
|
|
Append(new UnsignedField<8>(frsky.usrProto));
|
|
if (version >= 216) {
|
|
Append(new UnsignedField<7>(frsky.voltsSource));
|
|
Append(new BoolField<1>(frsky.altitudeDisplayed));
|
|
}
|
|
else {
|
|
Append(new UnsignedField<8>(frsky.voltsSource));
|
|
}
|
|
Append(new ConversionField< SignedField<8> >(frsky.blades, -2));
|
|
Append(new UnsignedField<8>(frsky.currentSource));
|
|
|
|
Append(new UnsignedField<1>(frsky.screens[0].type));
|
|
Append(new UnsignedField<1>(frsky.screens[1].type));
|
|
Append(new UnsignedField<1>(frsky.screens[2].type));
|
|
Append(new SpareBitsField<5>());
|
|
|
|
for (int i=0; i<3; i++) {
|
|
Append(new FrskyScreenField(frsky.screens[i], board, version));
|
|
}
|
|
if (IS_TARANIS(board))
|
|
Append(new ConversionField< UnsignedField<8> >(frsky.varioSource, &varioConversionTable, "Vario Source"));
|
|
else
|
|
Append(new UnsignedField<8>(frsky.varioSource));
|
|
Append(new SignedField<8>(frsky.varioCenterMax));
|
|
Append(new SignedField<8>(frsky.varioCenterMin));
|
|
Append(new SignedField<8>(frsky.varioMin));
|
|
Append(new SignedField<8>(frsky.varioMax));
|
|
for (int i=0; i<2; i++) {
|
|
Append(new ConversionField< UnsignedField<2> >(frsky.rssiAlarms[i].level, &rssiConversionTable[i], "RSSI"));
|
|
Append(new ConversionField< SignedField<6> >(frsky.rssiAlarms[i].value, -45+i*3));
|
|
}
|
|
if (version >= 216) {
|
|
Append(new BoolField<1>(frsky.mAhPersistent));
|
|
Append(new UnsignedField<15>(frsky.storedMah));
|
|
Append(new SignedField<8>(frsky.fasOffset));
|
|
}
|
|
}
|
|
else {
|
|
for (int i=0; i<2; i++) {
|
|
Append(new UnsignedField<8>(frsky.channels[i].ratio, "Ratio"));
|
|
Append(new SignedField<12>(frsky.channels[i].offset, "Offset"));
|
|
Append(new UnsignedField<4>(frsky.channels[i].type, "Type"));
|
|
for (int j=0; j<2; j++)
|
|
Append(new UnsignedField<8>(frsky.channels[i].alarms[j].value, "Alarm value"));
|
|
for (int j=0; j<2; j++)
|
|
Append(new UnsignedField<2>(frsky.channels[i].alarms[j].level));
|
|
for (int j=0; j<2; j++)
|
|
Append(new UnsignedField<1>(frsky.channels[i].alarms[j].greater));
|
|
Append(new UnsignedField<2>(frsky.channels[i].multiplier, 0, 3, "Multiplier"));
|
|
}
|
|
Append(new UnsignedField<2>(frsky.usrProto, "USR Proto"));
|
|
Append(new ConversionField< UnsignedField<2> >((unsigned int &)frsky.blades, -2));
|
|
Append(new UnsignedField<1>(frsky.screens[0].type));
|
|
Append(new UnsignedField<1>(frsky.screens[1].type));
|
|
Append(new UnsignedField<2>(frsky.voltsSource, "Volts Source"));
|
|
Append(new SignedField<4>(frsky.varioMin, "Vario Min"));
|
|
Append(new SignedField<4>(frsky.varioMax));
|
|
for (int i=0; i<2; i++) {
|
|
Append(new ConversionField< UnsignedField<2> >(frsky.rssiAlarms[i].level, &rssiConversionTable[i], "RSSI level"));
|
|
Append(new ConversionField< SignedField<6> >(frsky.rssiAlarms[i].value, -45+i*3, 0, 0, 100, "RSSI value"));
|
|
}
|
|
for (int i=0; i<2; i++) {
|
|
Append(new FrskyScreenField(frsky.screens[i], board, version));
|
|
}
|
|
Append(new UnsignedField<3>(frsky.varioSource));
|
|
Append(new SignedField<5>(frsky.varioCenterMin));
|
|
Append(new UnsignedField<3>(frsky.currentSource));
|
|
Append(new SignedField<8>(frsky.varioCenterMax));
|
|
if (version >= 216) {
|
|
// TODO int8_t fasOffset;
|
|
Append(new SpareBitsField<8>());
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
RSSIConversionTable rssiConversionTable[2];
|
|
VarioConversionTable varioConversionTable;
|
|
};
|
|
|
|
class MavlinkField: public StructField {
|
|
public:
|
|
MavlinkField(MavlinkData & mavlink, BoardEnum board, unsigned int version):
|
|
StructField("MavLink")
|
|
{
|
|
Append(new UnsignedField<4>(mavlink.rc_rssi_scale, "Rc_rssi_scale"));
|
|
Append(new UnsignedField<1>(mavlink.pc_rssi_en, "Pc_rssi_en"));
|
|
Append(new SpareBitsField<3>());
|
|
Append(new SpareBitsField<8>());
|
|
Append(new SpareBitsField<8>());
|
|
Append(new SpareBitsField<8>());
|
|
}
|
|
};
|
|
|
|
int exportPpmDelay(int delay) { return (delay - 300) / 50; }
|
|
int importPpmDelay(int delay) { return 300 + 50 * delay; }
|
|
|
|
OpenTxModelData::OpenTxModelData(ModelData & modelData, BoardEnum board, unsigned int version, unsigned int variant):
|
|
TransformedField(internalField),
|
|
internalField("ModelData"),
|
|
modelData(modelData),
|
|
board(board),
|
|
version(version),
|
|
variant(variant),
|
|
protocolsConversionTable(board),
|
|
throttleSourceConversionTable(board, version)
|
|
{
|
|
sprintf(name, "Model %s", modelData.name);
|
|
|
|
if (HAS_LARGE_LCD(board))
|
|
internalField.Append(new ZCharField<12>(modelData.name));
|
|
else
|
|
internalField.Append(new ZCharField<10>(modelData.name));
|
|
|
|
bool afterrelease21March2013 = IS_AFTER_RELEASE_21_MARCH_2013(board, version);
|
|
|
|
if (afterrelease21March2013)
|
|
internalField.Append(new UnsignedField<8>(modelData.modelId));
|
|
|
|
if (IS_TARANIS(board) && version >= 215) {
|
|
internalField.Append(new CharField<10>(modelData.bitmap));
|
|
}
|
|
|
|
for (int i=0; i<O9X_MAX_TIMERS; i++) {
|
|
internalField.Append(new SwitchField<8>(modelData.timers[i].mode, board, version, POPULATE_TIMER_MODES));
|
|
if ((IS_ARM(board) || IS_2560(board)) && version >= 216) {
|
|
internalField.Append(new UnsignedField<16>(modelData.timers[i].val));
|
|
internalField.Append(new UnsignedField<2>(modelData.timers[i].countdownBeep));
|
|
internalField.Append(new BoolField<1>(modelData.timers[i].minuteBeep));
|
|
internalField.Append(new BoolField<1>(modelData.timers[i].persistent));
|
|
internalField.Append(new SpareBitsField<4>());
|
|
internalField.Append(new SignedField<16>(modelData.timers[i].pvalue));
|
|
}
|
|
else if (afterrelease21March2013) {
|
|
internalField.Append(new UnsignedField<12>(modelData.timers[i].val));
|
|
internalField.Append(new BoolField<1>((bool &)modelData.timers[i].countdownBeep));
|
|
internalField.Append(new BoolField<1>(modelData.timers[i].minuteBeep));
|
|
if (HAS_PERSISTENT_TIMERS(board)) {
|
|
internalField.Append(new BoolField<1>(modelData.timers[i].persistent));
|
|
internalField.Append(new SpareBitsField<1>());
|
|
internalField.Append(new SignedField<16>(modelData.timers[i].pvalue));
|
|
}
|
|
else {
|
|
internalField.Append(new SpareBitsField<2>());
|
|
}
|
|
}
|
|
else {
|
|
internalField.Append(new UnsignedField<16>(modelData.timers[i].val));
|
|
if (HAS_PERSISTENT_TIMERS(board)) {
|
|
internalField.Append(new BoolField<1>(modelData.timers[i].persistent));
|
|
internalField.Append(new SpareBitsField<15>());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_TARANIS(board))
|
|
internalField.Append(new SpareBitsField<3>());
|
|
else
|
|
internalField.Append(new ConversionField< SignedField<3> >(modelData.moduleData[0].protocol, &protocolsConversionTable, "Protocol", ::QObject::tr("OpenTX doesn't accept this protocol")));
|
|
|
|
internalField.Append(new BoolField<1>(modelData.thrTrim));
|
|
|
|
if (IS_TARANIS(board) || (IS_ARM(board) && version >= 216))
|
|
internalField.Append(new SpareBitsField<4>());
|
|
else
|
|
internalField.Append(new ConversionField< SignedField<4> >(modelData.moduleData[0].channelsCount, &channelsConversionTable, "Channels number", ::QObject::tr("OpenTX doesn't allow this number of channels")));
|
|
|
|
if (version >= 216)
|
|
internalField.Append(new SignedField<3>(modelData.trimInc));
|
|
else
|
|
internalField.Append(new ConversionField< SignedField<3> >(modelData.trimInc, +2));
|
|
|
|
internalField.Append(new BoolField<1>(modelData.disableThrottleWarning));
|
|
|
|
if (IS_TARANIS(board) || (IS_ARM(board) && version >= 216))
|
|
internalField.Append(new BoolField<1>(modelData.displayText));
|
|
else
|
|
internalField.Append(new BoolField<1>(modelData.moduleData[0].ppmPulsePol));
|
|
|
|
internalField.Append(new BoolField<1>(modelData.extendedLimits));
|
|
internalField.Append(new BoolField<1>(modelData.extendedTrims));
|
|
internalField.Append(new BoolField<1>(modelData.throttleReversed));
|
|
|
|
if (!IS_ARM(board) || version < 216) {
|
|
internalField.Append(new ConversionField< SignedField<8> >(modelData.moduleData[0].ppmDelay, exportPpmDelay, importPpmDelay));
|
|
}
|
|
|
|
if (IS_ARM(board) || board==BOARD_GRUVIN9X)
|
|
internalField.Append(new UnsignedField<16>(modelData.beepANACenter));
|
|
else
|
|
internalField.Append(new UnsignedField<8>(modelData.beepANACenter));
|
|
|
|
for (int i=0; i<MAX_MIXERS(board, version); i++)
|
|
internalField.Append(new MixField(modelData.mixData[i], board, version, &modelData));
|
|
for (int i=0; i<MAX_CHANNELS(board, version); i++)
|
|
internalField.Append(new LimitField(modelData.limitData[i], board, version));
|
|
for (int i=0; i<MAX_EXPOS(board, version); i++)
|
|
internalField.Append(new InputField(modelData.expoData[i], board, version));
|
|
internalField.Append(new CurvesField(modelData.curves, board, version));
|
|
for (int i=0; i<MAX_CUSTOM_SWITCHES(board, version); i++)
|
|
internalField.Append(new LogicalSwitchField(modelData.customSw[i], board, version, variant, &modelData));
|
|
for (int i=0; i<MAX_CUSTOM_FUNCTIONS(board, version); i++) {
|
|
if (IS_ARM(board))
|
|
internalField.Append(new ArmCustomFunctionField(modelData.funcSw[i], board, version, variant));
|
|
else
|
|
internalField.Append(new AvrCustomFunctionField(modelData.funcSw[i], board, version, variant));
|
|
}
|
|
internalField.Append(new HeliField(modelData.swashRingData, board, version, variant));
|
|
for (int i=0; i<MAX_PHASES(board, version); i++)
|
|
internalField.Append(new FlightModeField(modelData.phaseData[i], i, board, version));
|
|
|
|
if (!IS_ARM(board) || version < 216) {
|
|
internalField.Append(new SignedField<8>(modelData.moduleData[0].ppmFrameLength));
|
|
}
|
|
|
|
internalField.Append(new ConversionField< UnsignedField<8> >(modelData.thrTraceSrc, &throttleSourceConversionTable, "Throttle Source"));
|
|
|
|
if (!afterrelease21March2013) {
|
|
internalField.Append(new UnsignedField<8>(modelData.modelId));
|
|
}
|
|
|
|
if (IS_TARANIS(board))
|
|
internalField.Append(new SwitchesWarningField<16>(modelData.switchWarningStates, board, version));
|
|
else
|
|
internalField.Append(new SwitchesWarningField<8>(modelData.switchWarningStates, board, version));
|
|
|
|
if (version >= 216) {
|
|
internalField.Append(new UnsignedField<8>(modelData.nSwToWarn));
|
|
}
|
|
|
|
if ((board == BOARD_STOCK || (board == BOARD_M128 && version >= 215)) && (variant & GVARS_VARIANT)) {
|
|
for (int i=0; i<MAX_GVARS(board, version); i++) {
|
|
// on M64 GVARS are common to all phases, and there is no name
|
|
internalField.Append(new SignedField<16>(modelData.phaseData[0].gvars[i]));
|
|
}
|
|
}
|
|
|
|
if (board != BOARD_STOCK && (board != BOARD_M128 || version < 215)) {
|
|
for (int i=0; i<MAX_GVARS(board, version); i++) {
|
|
internalField.Append(new ZCharField<6>(modelData.gvars_names[i]));
|
|
if (version >= 216) {
|
|
internalField.Append(new BoolField<1>(modelData.gvars_popups[i]));
|
|
internalField.Append(new SpareBitsField<7>());
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((board != BOARD_STOCK && (board != BOARD_M128 || version < 215)) || (variant & FRSKY_VARIANT)) {
|
|
internalField.Append(new FrskyField(modelData.frsky, board, version));
|
|
}
|
|
else if ((board == BOARD_STOCK || board == BOARD_M128) && (variant & MAVLINK_VARIANT)) {
|
|
internalField.Append(new MavlinkField(modelData.mavlink, board, version));
|
|
}
|
|
|
|
if (IS_TARANIS(board) && version < 215) {
|
|
internalField.Append(new CharField<10>(modelData.bitmap));
|
|
}
|
|
|
|
int modulesCount = 2;
|
|
|
|
if (IS_TARANIS(board)) {
|
|
modulesCount = 3;
|
|
internalField.Append(new ConversionField< SignedField<8> >(modelData.moduleData[1].protocol, &protocolsConversionTable, "Protocol", ::QObject::tr("OpenTX doesn't accept this protocol")));
|
|
internalField.Append(new UnsignedField<8>(modelData.trainerMode));
|
|
}
|
|
|
|
if (IS_ARM(board) && version >= 215) {
|
|
for (int module=0; module<modulesCount; module++) {
|
|
internalField.Append(new SignedField<8>(subprotocols[module]));
|
|
internalField.Append(new UnsignedField<8>(modelData.moduleData[module].channelsStart));
|
|
internalField.Append(new ConversionField< SignedField<8> >(modelData.moduleData[module].channelsCount, -8));
|
|
internalField.Append(new UnsignedField<8>(modelData.moduleData[module].failsafeMode));
|
|
for (int i=0; i<32; i++)
|
|
internalField.Append(new SignedField<16>(modelData.moduleData[module].failsafeChannels[i]));
|
|
internalField.Append(new ConversionField< SignedField<8> >(modelData.moduleData[module].ppmDelay, exportPpmDelay, importPpmDelay));
|
|
internalField.Append(new SignedField<8>(modelData.moduleData[module].ppmFrameLength));
|
|
internalField.Append(new BoolField<8>(modelData.moduleData[module].ppmPulsePol));
|
|
}
|
|
}
|
|
|
|
if (board==BOARD_SKY9X && version >= 216) {
|
|
internalField.Append(new UnsignedField<8>(modelData.nPotsToWarn));
|
|
for (int i=0; i < GetEepromInterface()->getCapability(Pots); i++) {
|
|
internalField.Append(new SignedField<8>(modelData.potPosition[i]));
|
|
}
|
|
}
|
|
|
|
if (IS_TARANIS(board)) {
|
|
for (int i=0; i<MAX_CURVES(board, version); i++) {
|
|
internalField.Append(new ZCharField<6>(modelData.curves[i].name));
|
|
}
|
|
}
|
|
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
for (int i=0; i<7; i++) {
|
|
ScriptData & script = modelData.scriptData[i];
|
|
internalField.Append(new ZCharField<10>(script.filename));
|
|
internalField.Append(new ZCharField<10>(script.name));
|
|
for (int j=0; j<10; j++) {
|
|
internalField.Append(new SignedField<8>(script.inputs[j]));
|
|
}
|
|
}
|
|
for (int i=0; i<32; i++) {
|
|
internalField.Append(new ZCharField<4>(modelData.inputNames[i]));
|
|
}
|
|
internalField.Append(new UnsignedField<8>(modelData.nPotsToWarn));
|
|
for (int i=0; i < GetEepromInterface()->getCapability(Pots); i++) {
|
|
internalField.Append(new SignedField<8>(modelData.potPosition[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenTxModelData::beforeExport()
|
|
{
|
|
// qDebug() << QString("before export model") << modelData.name;
|
|
|
|
for (int module=0; module<3; module++) {
|
|
if (modelData.moduleData[module].protocol >= PXX_XJT_X16 && modelData.moduleData[module].protocol <= PXX_XJT_LR12)
|
|
subprotocols[module] = modelData.moduleData[module].protocol - PXX_XJT_X16;
|
|
else if (modelData.moduleData[module].protocol >= LP45 && modelData.moduleData[module].protocol <= DSMX)
|
|
subprotocols[module] = modelData.moduleData[module].protocol - LP45;
|
|
else
|
|
subprotocols[module] = (module==0 ? -1 : 0);
|
|
}
|
|
}
|
|
|
|
void OpenTxModelData::afterImport()
|
|
{
|
|
// qDebug() << QString("after import model") << modelData.name ;
|
|
|
|
if (IS_TARANIS(board) && version < 216) {
|
|
for (unsigned int i=0; i<NUM_STICKS; i++) {
|
|
for (int j=0; j<64; j++) {
|
|
ExpoData * expo = &modelData.expoData[j];
|
|
if (expo->mode == INPUT_MODE_BOTH && expo->chn == i && expo->phases == 0 && expo->swtch.type == SWITCH_TYPE_NONE)
|
|
break;
|
|
if (expo->mode == 0 || expo->chn > i) {
|
|
ExpoData * newExpo = modelData.insertInput(j);
|
|
newExpo->mode = INPUT_MODE_BOTH;
|
|
newExpo->srcRaw = RawSource(SOURCE_TYPE_STICK, i);
|
|
newExpo->chn = i;
|
|
newExpo->weight = 100;
|
|
break;
|
|
}
|
|
}
|
|
strncpy(modelData.inputNames[i], AnalogString(i).toLatin1().constData(), sizeof(modelData.inputNames[i])-1);
|
|
}
|
|
}
|
|
|
|
for (int module=0; module<3; module++) {
|
|
if (modelData.moduleData[module].protocol == PXX_XJT_X16 || modelData.moduleData[module].protocol == LP45) {
|
|
if (subprotocols[module] >= 0)
|
|
modelData.moduleData[module].protocol += subprotocols[module];
|
|
else
|
|
modelData.moduleData[module].protocol = OFF;
|
|
}
|
|
}
|
|
}
|
|
|
|
OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, BoardEnum board, unsigned int version, unsigned int variant):
|
|
TransformedField(internalField),
|
|
internalField("General Settings"),
|
|
generalData(generalData),
|
|
board(board),
|
|
version(version),
|
|
inputsCount(4 + MAX_POTS(board))
|
|
{
|
|
generalData.version = version;
|
|
generalData.variant = variant;
|
|
|
|
internalField.Append(new UnsignedField<8>(generalData.version));
|
|
if (version >= 213 || (!IS_ARM(board) && version >= 212))
|
|
internalField.Append(new UnsignedField<16>(generalData.variant));
|
|
|
|
if (version >= 216) {
|
|
for (int i=0; i<inputsCount; i++) {
|
|
internalField.Append(new SignedField<16>(generalData.calibMid[i]));
|
|
internalField.Append(new SignedField<16>(generalData.calibSpanNeg[i]));
|
|
internalField.Append(new SignedField<16>(generalData.calibSpanPos[i]));
|
|
}
|
|
}
|
|
else {
|
|
for (int i=0; i<inputsCount; i++) {
|
|
if (!IS_TARANIS(board) || i!=6)
|
|
internalField.Append(new SignedField<16>(generalData.calibMid[i]));
|
|
}
|
|
for (int i=0; i<inputsCount; i++) {
|
|
if (!IS_TARANIS(board) || i!=6)
|
|
internalField.Append(new SignedField<16>(generalData.calibSpanNeg[i]));
|
|
}
|
|
for (int i=0; i<inputsCount; i++) {
|
|
if (!IS_TARANIS(board) || i!=6)
|
|
internalField.Append(new SignedField<16>(generalData.calibSpanPos[i]));
|
|
}
|
|
}
|
|
|
|
internalField.Append(new UnsignedField<16>(chkSum));
|
|
internalField.Append(new UnsignedField<8>(generalData.currModel));
|
|
internalField.Append(new UnsignedField<8>(generalData.contrast));
|
|
internalField.Append(new UnsignedField<8>(generalData.vBatWarn));
|
|
internalField.Append(new SignedField<8>(generalData.vBatCalib));
|
|
internalField.Append(new SignedField<8>(generalData.backlightMode));
|
|
|
|
for (int i=0; i<NUM_STICKS; i++)
|
|
internalField.Append(new SignedField<16>(generalData.trainer.calib[i]));
|
|
for (int i=0; i<NUM_STICKS; i++) {
|
|
internalField.Append(new UnsignedField<6>(generalData.trainer.mix[i].src));
|
|
internalField.Append(new UnsignedField<2>(generalData.trainer.mix[i].mode));
|
|
internalField.Append(new SignedField<8>(generalData.trainer.mix[i].weight));
|
|
}
|
|
|
|
internalField.Append(new UnsignedField<8>(generalData.view, 0, MAX_VIEWS(board)-1));
|
|
|
|
internalField.Append(new SpareBitsField<2>());
|
|
internalField.Append(new BoolField<1>(generalData.fai));
|
|
internalField.Append(new SignedField<2>((int &)generalData.beeperMode));
|
|
internalField.Append(new BoolField<1>(generalData.flashBeep));
|
|
internalField.Append(new BoolField<1>(generalData.disableMemoryWarning));
|
|
internalField.Append(new BoolField<1>(generalData.disableAlarmWarning));
|
|
|
|
internalField.Append(new UnsignedField<2>(generalData.stickMode));
|
|
internalField.Append(new SignedField<5>(generalData.timezone));
|
|
internalField.Append(new SpareBitsField<1>());
|
|
|
|
internalField.Append(new UnsignedField<8>(generalData.inactivityTimer));
|
|
if (IS_9X(board) && version >= 215) {
|
|
internalField.Append(new UnsignedField<3>(generalData.mavbaud));
|
|
}
|
|
else {
|
|
internalField.Append(new SpareBitsField<1>());
|
|
internalField.Append(new BoolField<1>(generalData.minuteBeep));
|
|
internalField.Append(new BoolField<1>(generalData.preBeep));
|
|
}
|
|
if (version >= 216 && IS_TARANIS(board))
|
|
internalField.Append(new SignedField<3>(generalData.splashDuration));
|
|
else if (version >= 213 || (!IS_ARM(board) && version >= 212))
|
|
internalField.Append(new UnsignedField<3>(generalData.splashMode)); // TODO
|
|
else
|
|
internalField.Append(new SpareBitsField<3>());
|
|
internalField.Append(new SignedField<2>((int &)generalData.hapticMode));
|
|
|
|
internalField.Append(new SpareBitsField<8>());
|
|
internalField.Append(new UnsignedField<8>(generalData.backlightDelay));
|
|
internalField.Append(new UnsignedField<8>(generalData.templateSetup));
|
|
internalField.Append(new SignedField<8>(generalData.PPM_Multiplier));
|
|
internalField.Append(new SignedField<8>(generalData.hapticLength));
|
|
|
|
if (version < 216 || !IS_9X(board)) {
|
|
internalField.Append(new UnsignedField<8>(generalData.reNavigation));
|
|
}
|
|
|
|
if (version >= 216 && !IS_TARANIS(board)) {
|
|
internalField.Append(new UnsignedField<4>(generalData.stickReverse));
|
|
internalField.Append(new SpareBitsField<4>());
|
|
}
|
|
|
|
internalField.Append(new SignedField<3>(generalData.beeperLength));
|
|
internalField.Append(new UnsignedField<3>(generalData.hapticStrength));
|
|
internalField.Append(new UnsignedField<1>(generalData.gpsFormat));
|
|
internalField.Append(new SpareBitsField<1>()); // unexpectedShutdown
|
|
|
|
internalField.Append(new UnsignedField<8>(generalData.speakerPitch));
|
|
|
|
if (IS_ARM(board))
|
|
internalField.Append(new ConversionField< SignedField<8> >(generalData.speakerVolume, -12, 0, 0, 23, "Volume"));
|
|
else
|
|
internalField.Append(new ConversionField< SignedField<8> >(generalData.speakerVolume, -7, 0, 0, 7, "Volume"));
|
|
|
|
if (version >= 214 || (!IS_ARM(board) && version >= 213)) {
|
|
internalField.Append(new SignedField<8>(generalData.vBatMin));
|
|
internalField.Append(new SignedField<8>(generalData.vBatMax));
|
|
}
|
|
|
|
if (IS_ARM(board)) {
|
|
internalField.Append(new UnsignedField<8>(generalData.backlightBright));
|
|
internalField.Append(new SignedField<8>(generalData.currentCalib));
|
|
if (version >= 213) {
|
|
internalField.Append(new SignedField<8>(generalData.temperatureWarn)); // TODO
|
|
internalField.Append(new UnsignedField<8>(generalData.mAhWarn));
|
|
internalField.Append(new SpareBitsField<16>()); // mAhUsed
|
|
internalField.Append(new SpareBitsField<32>()); // globalTimer
|
|
internalField.Append(new SignedField<8>(generalData.temperatureCalib)); // TODO
|
|
internalField.Append(new UnsignedField<8>(generalData.btBaudrate)); // TODO
|
|
internalField.Append(new BoolField<8>(generalData.optrexDisplay)); //TODO
|
|
internalField.Append(new UnsignedField<8>(generalData.sticksGain)); // TODO
|
|
}
|
|
if (version >= 214) {
|
|
internalField.Append(new UnsignedField<8>(generalData.rotarySteps)); // TODO
|
|
internalField.Append(new UnsignedField<8>(generalData.countryCode));
|
|
internalField.Append(new UnsignedField<8>(generalData.imperial));
|
|
}
|
|
if (version >= 215) {
|
|
internalField.Append(new CharField<2>(generalData.ttsLanguage));
|
|
internalField.Append(new SignedField<8>(generalData.beepVolume));
|
|
internalField.Append(new SignedField<8>(generalData.wavVolume));
|
|
internalField.Append(new SignedField<8>(generalData.varioVolume));
|
|
if (version >= 216) {
|
|
internalField.Append(new SignedField<8>(generalData.varioPitch));
|
|
internalField.Append(new SignedField<8>(generalData.varioRange));
|
|
internalField.Append(new SignedField<8>(generalData.varioRepeat));
|
|
}
|
|
internalField.Append(new SignedField<8>(generalData.backgroundVolume));
|
|
}
|
|
if (IS_TARANIS(board) && version >= 216) {
|
|
internalField.Append(new UnsignedField<8>(generalData.hw_uartMode));
|
|
for (int i=0; i<4; i++) {
|
|
internalField.Append(new UnsignedField<2>(potsType[i]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenTxGeneralData::beforeExport()
|
|
{
|
|
uint16_t sum = 0;
|
|
if (version >= 216) {
|
|
int count = 0;
|
|
for (int i=0; i<inputsCount; i++) {
|
|
sum += generalData.calibMid[i];
|
|
if (++count == 12) break;
|
|
sum += generalData.calibSpanNeg[i];
|
|
if (++count == 12) break;
|
|
sum += generalData.calibSpanPos[i];
|
|
if (++count == 12) break;
|
|
}
|
|
for (int i=0; i<4; i++) {
|
|
potsType[i] = generalData.potsType[i];
|
|
if (i<2 && potsType[i] == 1)
|
|
potsType[i] = 0;
|
|
}
|
|
}
|
|
else {
|
|
for (int i=0; i<inputsCount; i++)
|
|
sum += generalData.calibMid[i];
|
|
for (int i=0; i<5; i++)
|
|
sum += generalData.calibSpanNeg[i];
|
|
}
|
|
chkSum = sum;
|
|
}
|
|
|
|
void OpenTxGeneralData::afterImport()
|
|
{
|
|
for (int i=0; i<4; i++) {
|
|
if (i<2 && generalData.potsType[i] == 0)
|
|
generalData.potsType[i] = 1;
|
|
}
|
|
}
|