feat(EL18): Add AFHDS3 receiver options (#2470)

* Get config after switching model ID

* Remember set model ID and change it on the fly

* Add AFHDS3 options

* Fix compiler warning

* Fix box sizing

* Apply model config before editing options
This commit is contained in:
Raphael Coeffic
2022-10-09 19:54:55 +10:00
committed by GitHub
parent 9fa9a0c594
commit 8c8b24225d
8 changed files with 347 additions and 221 deletions
+3
View File
@@ -140,6 +140,9 @@ endif()
if(AFHDS2 OR AFHDS3)
add_gui_src(flysky_settings.cpp)
if(AFHDS3)
add_gui_src(afhds3_options.cpp)
endif()
endif()
if(MULTIMODULE)
+110
View File
@@ -0,0 +1,110 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "afhds3_options.h"
#include "opentx.h"
//#include "checkbox.h"
static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
#define SET_DIRTY()
static const char* _analog_outputs[] = { "PWM", "PPM" };
static const char* _bus_types[] = { "iBUS", "iBUS2", "SBUS" };
static const char* _v1_bus_types[] = { "PWM", "PPM", "SBUS", "iBUS IN", "iBUS OUT" };
AFHDS3_Options::AFHDS3_Options(uint8_t moduleIdx) : Page(ICON_MODEL_SETUP)
{
cfg = afhds3::getConfig(moduleIdx);
std::string title =
moduleIdx == INTERNAL_MODULE ? STR_INTERNALRF : STR_EXTERNALRF;
title += "\nAFHDS3";
header.setTitle(title);
auto form = new FormGroup(&body, rect_t{});
form->setFlexLayout();
form->padAll(lv_dpx(8));
FlexGridLayout grid(col_dsc, row_dsc, 2);
if (cfg->version == 0) {
auto vCfg = &cfg->v0;
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, "PWM frequency");
new NumberEdit(line, rect_t{}, 50, 400, GET_SET_DEFAULT(vCfg->PWMFrequency.Frequency));
line = form->newLine(&grid);
new StaticText(line, rect_t{}, "PWM sychronized");
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(vCfg->PWMFrequency.Synchronized));
line = form->newLine(&grid);
new StaticText(line, rect_t{}, "Analog output");
new Choice(line, rect_t{}, _analog_outputs,
afhds3::SES_ANALOG_OUTPUT_PWM, afhds3::SES_ANALOG_OUTPUT_PPM,
GET_SET_DEFAULT(vCfg->AnalogOutput));
line = form->newLine(&grid);
new StaticText(line, rect_t{}, "External bus type");
new Choice(line, rect_t{}, _bus_types,
afhds3::EB_BT_IBUS1, afhds3::EB_BT_SBUS1,
GET_SET_DEFAULT(vCfg->ExternalBusType));
} else {
auto vCfg = &cfg->v1;
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, "PWM frequency");
new NumberEdit(line, rect_t{}, 50, 400,
GET_DEFAULT(vCfg->PWMFrequenciesV1.PWMFrequencies[0]),
[=](int16_t newVal) {
for (uint8_t i = 0; i < SES_NB_MAX_CHANNELS; i++) {
vCfg->PWMFrequenciesV1.PWMFrequencies[i] = newVal;
}
});
line = form->newLine(&grid);
new StaticText(line, rect_t{}, "PWM sychronized");
new CheckBox(
line, rect_t{}, GET_DEFAULT(vCfg->PWMFrequenciesV1.Synchronized),
[=](uint8_t newVal) {
vCfg->PWMFrequenciesV1.Synchronized = newVal ? 0xFFFFFFFF : 0;
});
for (uint8_t i = 0; i < SES_NPT_NB_MAX_PORTS; i++) {
line = form->newLine(&grid);
std::string portName = "NP";
portName += 'A' + i;
new StaticText(line, rect_t{}, portName.c_str());
new Choice(line, rect_t{}, _v1_bus_types, afhds3::SES_NPT_PWM,
afhds3::SES_NPT_IBUS1_OUT,
GET_SET_DEFAULT(vCfg->NewPortTypes[i]));
}
}
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "page.h"
#include "pulses/afhds3_config.h"
class AFHDS3_Options : public Page
{
afhds3::Config_u* cfg;
public:
AFHDS3_Options(uint8_t moduleIdx);
};
+16 -39
View File
@@ -22,6 +22,10 @@
#include "flysky_settings.h"
#include "opentx.h"
#if defined(AFHDS3)
#include "afhds3_options.h"
#endif
#include "pulses/flysky.h"
#include "pulses/afhds3.h"
@@ -132,50 +136,23 @@ void FlySkySettings::update()
new StaticText(line, rect_t{}, STR_TYPE, 0, COLOR_THEME_PRIMARY1);
auto box = new FormGroup(line, rect_t{});
box->setFlexLayout(LV_FLEX_FLOW_ROW);
new Choice(box, rect_t{}, _afhds3_region, 1, afhds3::LNK_ES_FCC,
GET_SET_DEFAULT(md->afhds3.emi));
box->setFlexLayout(LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_style_grid_cell_x_align(box->getLvObj(), LV_GRID_ALIGN_STRETCH, 0);
new Choice(box, rect_t{}, _afhds3_phy_mode, 0, afhds3::PHYMODE_MAX,
GET_SET_DEFAULT(md->afhds3.phyMode));
// // Power source
// line = newLine(&grid);
// new StaticText(line, rect_t{}, STR_AFHDS3_POWER_SOURCE, 0,
// COLOR_THEME_PRIMARY1);
// new DynamicText(line, rect_t{}, [=] {
// char msg[64] = "";
// getModuleSyncStatusString(moduleIdx, msg);
// return std::string(msg);
// });
new Choice(box, rect_t{}, _afhds3_region,
afhds3::LNK_ES_CE, afhds3::LNK_ES_FCC,
GET_SET_DEFAULT(md->afhds3.emi));
// // RX Freq
// line = newLine(&grid);
// new StaticText(line, rect_t{}, STR_AFHDS3_RX_FREQ, 0, COLOR_THEME_PRIMARY1);
// auto edit = new NumberEdit(line, rect_t{}, AFHDS3_MIN_FREQ, AFHDS3_MAX_FREQ,
// GET_DEFAULT(md->afhds3.rxFreq()));
// edit->setSetValueHandler(
// [=](int32_t newValue) { md->afhds3.setRxFreq((uint16_t)newValue); });
// edit->setSuffix(STR_HZ);
// // Module actual power
// line = newLine(&grid);
// new StaticText(line, rect_t{}, STR_AFHDS3_ACTUAL_POWER, 0,
// COLOR_THEME_PRIMARY1);
// new DynamicText(line, rect_t{}, [=] {
// char msg[64] = "";
// getStringAtIndex(msg, STR_AFHDS3_POWERS, actualAfhdsRunPower(moduleIdx));
// return std::string(msg);
// });
// // Module power
// line = newLine(&grid);
// new StaticText(line, rect_t{}, STR_RF_POWER, 0, COLOR_THEME_PRIMARY1);
// new Choice(line, rect_t{}, STR_AFHDS3_POWERS,
// afhds3::RUN_POWER::RUN_POWER_FIRST,
// afhds3::RUN_POWER::RUN_POWER_LAST,
// GET_SET_DEFAULT(md->afhds3.runPower));
uint8_t module = moduleIdx;
new TextButton(box, rect_t{}, STR_MODULE_OPTIONS,
[=]() {
afhds3::applyModelConfig(module);
new AFHDS3_Options(module);
return 0;
});
}
#endif
}
+1 -1
View File
@@ -64,7 +64,7 @@ void mixerSchedulerISRTrigger();
#define mixerSchedulerStart()
#define mixerSchedulerStop()
#define mixerSchedulerResetTimer()
#define mixerSchedulerSetPeriod(m,p)
#define mixerSchedulerSetPeriod(m,p) ((void)(p))
#define mixerSchedulerClearTrigger()
#define mixerSchedulerEnableTrigger()
+72 -180
View File
@@ -21,11 +21,12 @@
#include "afhds3.h"
#include "afhds3_transport.h"
#include "afhds3_config.h"
#include "pulses.h"
#include "../debug.h"
#include "../definitions.h"
// #include <cstdio>
#include "telemetry/telemetry.h"
#include "mixer_scheduler.h"
@@ -62,24 +63,24 @@ static uint8_t _phyMode_channels[] = {
12, // ROUTINE_LORA_12CH
};
enum COMMAND_DIRECTION
{
RADIO_TO_MODULE = 0,
MODULE_TO_RADIO = 1
};
// enum COMMAND_DIRECTION
// {
// RADIO_TO_MODULE = 0,
// MODULE_TO_RADIO = 1
// };
enum DATA_TYPE
{
READY_DT, // 8 bytes 0x01 Not ready 0x02 Ready
STATE_DT, // See MODULE_STATE
MODE_DT,
MOD_CONFIG_DT,
CHANNELS_DT,
TELEMETRY_DT,
MODULE_POWER_DT,
MODULE_VERSION_DT,
EMPTY_DT,
};
// enum DATA_TYPE
// {
// READY_DT, // 8 bytes 0x01 Not ready 0x02 Ready
// STATE_DT, // See MODULE_STATE
// MODE_DT,
// MOD_CONFIG_DT,
// CHANNELS_DT,
// TELEMETRY_DT,
// MODULE_POWER_DT,
// MODULE_VERSION_DT,
// EMPTY_DT,
// };
//enum used by command response -> translate to ModuleState
enum MODULE_READY_E
@@ -122,135 +123,6 @@ enum CMD_RESULT
SUCCESS = 0x02,
};
enum BIND_POWER
{
MIN_16dBm = 0x00,
BIND_POWER_FIRST = MIN_16dBm,
MIN_5dBm = 0x01,
MIN_0dbm = 0x02,
PLUS_5dBm = 0x03,
PLUS_14dBm = 0x04,
BIND_POWER_LAST = PLUS_14dBm,
};
// enum EMI_STANDARD
// {
// FCC = 0x00,
// CE = 0x01
// };
enum TELEMETRY
{
TELEMETRY_DISABLED = 0x00,
TELEMETRY_ENABLED = 0x01
};
enum PULSE_MODE
{
PWM_MODE = 0x00,
PPM_MODE = 0x01,
};
enum SERIAL_MODE
{
IBUS = 0x00,
SBUS_MODE = 0x02
};
// Old format for FRM302
// PACK(struct Config_s {
// uint8_t bindPower;
// uint8_t runPower;
// uint8_t emiStandard;
// uint8_t telemetry;
// uint16_t pwmFreq;
// uint8_t pulseMode;
// uint8_t serialMode;
// uint8_t channelCount;
// uint16_t failSafeTimout;
// int16_t failSafeMode[AFHDS3_MAX_CHANNELS];
// });
PACK(struct sSES_PWMFrequencyV0 {
uint16_t Frequency : 15; // From 50 to 400Hz
uint16_t Synchronized : 1; // 1=Synchronize the PWM output to the RF cycle
// (lower latency but unstable frequency)
});
enum eSES_PA_SetAnalogOutput {
SES_ANALOG_OUTPUT_PWM = 0,
SES_ANALOG_OUTPUT_PPM
};
enum eEB_BusType {
EB_BT_IBUS1=0,
EB_BT_IBUS2,
EB_BT_SBUS1
};
// 48 bytes
PACK(struct sDATA_ConfigV0 {
uint8_t Version; // =0
uint8_t EMIStandard; // eLNK_EMIStandard
uint8_t IsTwoWay;
uint8_t PhyMode; // eDATA_PHYMODE
uint8_t SignalStrengthRCChannelNb; // 0xFF if not used, 0`18
uint16_t FailsafeTimeout; // in unit of ms
int16_t FailSafe[AFHDS3_MAX_CHANNELS];
uint8_t FailsafeOutputMode; //TRUE Or FALSE
sSES_PWMFrequencyV0 PWMFrequency;
uint8_t AnalogOutput; // eSES_PA_SetAnalogOutput
uint8_t ExternalBusType; // eEB_BusType
});
#define SES_NB_MAX_CHANNELS (32)
#define SES_NPT_NB_MAX_PORTS (4)
enum eSES_NewPortType {
SES_NPT_PWM,
SES_NPT_PPM,
SES_NPT_SBUS,
SES_NPT_IBUS1_IN,
SES_NPT_IBUS1_OUT,
SES_NPT_IBUS2,
SES_NPT_IBUS2_HUB_PORT,
SES_NPT_WSTX,
SES_NPT_WSRX,
SES_NPT_NONE=0xFF
};
PACK(struct sSES_PWMFrequenciesAPPV1 {
// One unsigned short per
// channel, From 50 to 400Hz,
// 1:1000Hz,2:833Hz
uint16_t PWMFrequencies[SES_NB_MAX_CHANNELS];
// 1 bit per channel, 32 channels total
uint32_t Synchronized;
});
// 116 bytes
PACK(struct sDATA_ConfigV1 {
uint8_t Version; // =1
uint8_t EMIStandard; // eLNK_EMIStandard
uint8_t IsTwoWay;
uint8_t PhyMode; // eDATA_PHYMODE
uint8_t SignalStrengthRCChannelNb; // 0xFF if not used , 0`18
uint16_t FailsafeTimeout; // in unit of ms
int16_t FailSafe[AFHDS3_MAX_CHANNELS];
uint8_t FailsafeOutputMode; // TRUE Or FALSE
uint8_t NewPortTypes[SES_NPT_NB_MAX_PORTS]; // eSES_NewPortType
sSES_PWMFrequenciesAPPV1 PWMFrequenciesV1;
});
union Config_u
{
uint8_t version;
sDATA_ConfigV0 v0;
sDATA_ConfigV1 v1;
uint8_t buffer[sizeof(sDATA_ConfigV1)];
};
enum CHANNELS_DATA_MODE
{
CHANNELS = 0x01,
@@ -349,9 +221,13 @@ class ProtoState
*/
void stop();
Config_u* getConfig() { return &cfg; }
void applyConfigFromModel();
protected:
void setConfigFromModel();
void resetConfig(uint8_t version);
private:
//friendship declaration - use for passing telemetry
@@ -391,6 +267,7 @@ class ProtoState
ModuleState state;
bool modelIDSet;
uint8_t modelID;
/**
* Command count used for counting actual number of commands sent in run mode
@@ -438,7 +315,7 @@ static const char* const moduleStateText[] =
static const COMMAND periodicRequestCommands[] =
{
COMMAND::MODULE_STATE,
COMMAND::MODULE_GET_CONFIG,
// COMMAND::MODULE_GET_CONFIG,
COMMAND::VIRTUAL_FAILSAFE
};
@@ -513,7 +390,7 @@ void ProtoState::setupFrame()
if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_BIND) {
if (state != STATE_BINDING) {
TRACE("AFHDS3 [BIND]");
setConfigFromModel();
applyConfigFromModel();
trsp.sendFrame(COMMAND::MODULE_SET_CONFIG,
FRAME_TYPE::REQUEST_SET_EXPECT_DATA, cfg.buffer,
@@ -542,10 +419,19 @@ void ProtoState::setupFrame()
return;
} else {
modelIDSet = true;
modelID = g_model.header.modelId[module_index];
trsp.sendFrame(COMMAND::MODEL_ID, FRAME_TYPE::REQUEST_SET_EXPECT_DATA,
&g_model.header.modelId[module_index], 1);
// always fetch config after setting model ID
trsp.enqueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA);
return;
}
} else if (modelID != g_model.header.modelId[module_index]) {
modelIDSet = false;
auto mode = (uint8_t)MODULE_MODE_E::STANDBY;
trsp.sendFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &mode, 1);
return;
}
if (this->state == ModuleState::STATE_STANDBY) {
@@ -873,64 +759,58 @@ void ProtoState::stop()
trsp.sendFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &mode, 1);
}
void ProtoState::setConfigFromModel()
void ProtoState::resetConfig(uint8_t version)
{
if (moduleData->afhds3.phyMode < ROUTINE_FLCR1_18CH) {
cfg.version = 0;
memclear(&cfg, sizeof(cfg));
cfg.version = version;
if (cfg.version == 1) {
cfg.v1.SignalStrengthRCChannelNb = 0xFF;
cfg.v1.FailsafeTimeout = 500;
for (int i = 0; i < SES_NB_MAX_CHANNELS; i++)
cfg.v1.PWMFrequenciesV1.PWMFrequencies[i] = 50;
} else {
cfg.version = 1;
cfg.v0.SignalStrengthRCChannelNb = 0xFF;
cfg.v0.FailsafeTimeout = 500;
cfg.v0.PWMFrequency.Frequency = 50;
}
}
void ProtoState::applyConfigFromModel()
{
uint8_t version = 0;
if (moduleData->afhds3.phyMode >= ROUTINE_FLCR1_18CH) {
version = 1;
}
if (version != cfg.version) {
resetConfig(version);
}
if (cfg.version == 1) {
cfg.v1.EMIStandard = moduleData->afhds3.emi;
cfg.v1.IsTwoWay = moduleData->afhds3.telemetry;
cfg.v1.PhyMode = moduleData->afhds3.phyMode;
cfg.v1.SignalStrengthRCChannelNb = 0xFF;
// Failsafe
cfg.v1.FailsafeTimeout = 500;
setFailSafe(cfg.v1.FailSafe);
if (moduleData->failsafeMode != FAILSAFE_NOPULSES) {
cfg.v1.FailsafeOutputMode = true;
} else {
cfg.v1.FailsafeOutputMode = false;
}
// Serial output
memclear(&cfg.v1.NewPortTypes, sizeof(cfg.v1.NewPortTypes));
// PWM settings
for (int i = 0; i < SES_NB_MAX_CHANNELS; i++)
cfg.v1.PWMFrequenciesV1.PWMFrequencies[i] = 50;
cfg.v1.PWMFrequenciesV1.Synchronized = 0;
} else {
cfg.v0.EMIStandard = moduleData->afhds3.emi;
cfg.v0.IsTwoWay = moduleData->afhds3.telemetry;
cfg.v0.PhyMode = moduleData->afhds3.phyMode;
cfg.v0.SignalStrengthRCChannelNb = 0xFF;
// Failsafe
cfg.v0.FailsafeTimeout = 500;
setFailSafe(cfg.v0.FailSafe);
if (moduleData->failsafeMode != FAILSAFE_NOPULSES) {
cfg.v0.FailsafeOutputMode = true;
} else {
cfg.v0.FailsafeOutputMode = false;
}
// PWM settings
cfg.v0.PWMFrequency.Frequency = 50;
cfg.v0.PWMFrequency.Synchronized = 0;
// PWM/PPM
cfg.v0.AnalogOutput = 0;
// iBUS/SBUS
cfg.v0.ExternalBusType = EB_BT_IBUS1;
}
}
@@ -969,6 +849,18 @@ uint8_t ProtoState::setFailSafe(int16_t* target)
return (uint8_t) (AFHDS3_MAX_CHANNELS);
}
Config_u* getConfig(uint8_t module)
{
auto p_state = &protoState[module];
return p_state->getConfig();
}
void applyModelConfig(uint8_t module)
{
auto p_state = &protoState[module];
p_state->applyConfigFromModel();
}
static void* initExternal(uint8_t module)
{
#if defined(AFHDS3_EXT_UART)
-1
View File
@@ -36,7 +36,6 @@
#define AFHDS3_MIN_FREQ 50
#define AFHDS3_MAX_FREQ 400
#define AFHDS3_MAX_CHANNELS 18
#define AFHDS3_FAILSAFE_MIN -15000
#define AFHDS3_FAILSAFE_MAX 15000
+112
View File
@@ -0,0 +1,112 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#define AFHDS3_MAX_CHANNELS 18
namespace afhds3
{
PACK(struct sSES_PWMFrequencyV0 {
uint16_t Frequency : 15; // From 50 to 400Hz
uint16_t Synchronized : 1; // 1=Synchronize the PWM output to the RF cycle
// (lower latency but unstable frequency)
});
enum eSES_PA_SetAnalogOutput {
SES_ANALOG_OUTPUT_PWM = 0,
SES_ANALOG_OUTPUT_PPM
};
enum eEB_BusType {
EB_BT_IBUS1=0,
EB_BT_IBUS2,
EB_BT_SBUS1
};
// 48 bytes
PACK(struct sDATA_ConfigV0 {
uint8_t Version; // =0
uint8_t EMIStandard; // eLNK_EMIStandard
uint8_t IsTwoWay;
uint8_t PhyMode; // eDATA_PHYMODE
uint8_t SignalStrengthRCChannelNb; // 0xFF if not used, 0`18
uint16_t FailsafeTimeout; // in unit of ms
int16_t FailSafe[AFHDS3_MAX_CHANNELS];
uint8_t FailsafeOutputMode; //TRUE Or FALSE
sSES_PWMFrequencyV0 PWMFrequency;
uint8_t AnalogOutput; // eSES_PA_SetAnalogOutput
uint8_t ExternalBusType; // eEB_BusType
});
#define SES_NB_MAX_CHANNELS (32)
#define SES_NPT_NB_MAX_PORTS (4)
enum eSES_NewPortType {
SES_NPT_PWM,
SES_NPT_PPM,
SES_NPT_SBUS,
SES_NPT_IBUS1_IN,
SES_NPT_IBUS1_OUT,
SES_NPT_IBUS2,
SES_NPT_IBUS2_HUB_PORT,
SES_NPT_WSTX,
SES_NPT_WSRX,
SES_NPT_NONE=0xFF
};
PACK(struct sSES_PWMFrequenciesAPPV1 {
// One unsigned short per
// channel, From 50 to 400Hz,
// 1:1000Hz,2:833Hz
uint16_t PWMFrequencies[SES_NB_MAX_CHANNELS];
// 1 bit per channel, 32 channels total
uint32_t Synchronized;
});
// 116 bytes
PACK(struct sDATA_ConfigV1 {
uint8_t Version; // =1
uint8_t EMIStandard; // eLNK_EMIStandard
uint8_t IsTwoWay;
uint8_t PhyMode; // eDATA_PHYMODE
uint8_t SignalStrengthRCChannelNb; // 0xFF if not used , 0`18
uint16_t FailsafeTimeout; // in unit of ms
int16_t FailSafe[AFHDS3_MAX_CHANNELS];
uint8_t FailsafeOutputMode; // TRUE Or FALSE
uint8_t NewPortTypes[SES_NPT_NB_MAX_PORTS]; // eSES_NewPortType
sSES_PWMFrequenciesAPPV1 PWMFrequenciesV1;
});
union Config_u
{
uint8_t version;
sDATA_ConfigV0 v0;
sDATA_ConfigV1 v1;
uint8_t buffer[sizeof(sDATA_ConfigV1)];
};
Config_u* getConfig(uint8_t moduleIdx);
void applyModelConfig(uint8_t moduleIdx);
};