Merge pull request #728 from EdgeTX/nv14-internal-module
Nv14 internal module
This commit is contained in:
+13
-1
@@ -463,8 +463,18 @@ PACK(struct ModuleData {
|
||||
#if defined(AFHDS2)
|
||||
NOBACKUP(struct {
|
||||
uint8_t rx_id[4];
|
||||
uint8_t mode;
|
||||
uint8_t mode:3;
|
||||
uint8_t rfPower:1;
|
||||
uint8_t reserved:4;
|
||||
uint8_t rx_freq[2];
|
||||
|
||||
void setDefault() {
|
||||
rx_id[0] = rx_id[1] = rx_id[2] = rx_id[3] = 0;
|
||||
mode = 0;
|
||||
rfPower = 0;
|
||||
rx_freq[0] = 50;
|
||||
rx_freq[1] = 0;
|
||||
}
|
||||
} flysky);
|
||||
#endif
|
||||
#if defined(AFHDS3)
|
||||
@@ -475,6 +485,8 @@ PACK(struct ModuleData {
|
||||
uint8_t telemetry:1;
|
||||
uint16_t failsafeTimeout;
|
||||
uint8_t rx_freq[2];
|
||||
uint8_t mode:2;
|
||||
uint8_t reserved:6;
|
||||
uint16_t rxFreq()
|
||||
{
|
||||
return (uint16_t)rx_freq[0] | (((uint16_t)rx_freq[1]) << 8);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "model_setup.h"
|
||||
#include "multi_rfprotos.h"
|
||||
#include "io/multi_protolist.h"
|
||||
#include "pulses/flysky.h"
|
||||
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
@@ -803,46 +804,178 @@ class ModuleWindow : public FormGroup {
|
||||
|
||||
// Module parameters
|
||||
if (isModuleXJT(moduleIdx)) {
|
||||
auto xjtChoice = new Choice(this, grid.getFieldSlot(2, 1), STR_XJT_ACCST_RF_PROTOCOLS, MODULE_SUBTYPE_PXX1_OFF, MODULE_SUBTYPE_PXX1_ACCST_LR12,
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].rfProtocol));
|
||||
xjtChoice->setAvailableHandler([](int index) {
|
||||
return index != MODULE_SUBTYPE_PXX1_OFF;
|
||||
});
|
||||
}
|
||||
else if (isModuleDSM2(moduleIdx)) {
|
||||
new Choice(this, grid.getFieldSlot(2, 1), STR_DSM_PROTOCOLS, DSM2_PROTO_LP45, DSM2_PROTO_DSMX,
|
||||
auto xjtChoice = new Choice(
|
||||
this, grid.getFieldSlot(2, 1), STR_XJT_ACCST_RF_PROTOCOLS,
|
||||
MODULE_SUBTYPE_PXX1_OFF, MODULE_SUBTYPE_PXX1_ACCST_LR12,
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].rfProtocol));
|
||||
xjtChoice->setAvailableHandler(
|
||||
[](int index) { return index != MODULE_SUBTYPE_PXX1_OFF; });
|
||||
} else if (isModuleDSM2(moduleIdx)) {
|
||||
new Choice(this, grid.getFieldSlot(2, 1), STR_DSM_PROTOCOLS,
|
||||
DSM2_PROTO_LP45, DSM2_PROTO_DSMX,
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].rfProtocol));
|
||||
} else if (isModuleR9M(moduleIdx)) {
|
||||
rfChoice =
|
||||
new Choice(this, grid.getFieldSlot(2, 1), STR_R9M_REGION,
|
||||
MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_EU,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].subType),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
} else if (isModulePXX2(moduleIdx)) {
|
||||
rfChoice =
|
||||
new Choice(this, grid.getFieldSlot(2, 1), STR_ISRM_RF_PROTOCOLS, 0,
|
||||
MODULE_SUBTYPE_ISRM_PXX2_ACCST_LR12,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].subType),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
}
|
||||
else if (isModuleR9M(moduleIdx)) {
|
||||
rfChoice = new Choice(this, grid.getFieldSlot(2, 1), STR_R9M_REGION, MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_EU,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].subType),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
}
|
||||
else if (isModulePXX2(moduleIdx)) {
|
||||
rfChoice = new Choice(this, grid.getFieldSlot(2, 1), STR_ISRM_RF_PROTOCOLS, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_LR12,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].subType),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
}
|
||||
#if defined(AFHDS2) || defined(AFHDS3)
|
||||
else if (isModuleFlySky(moduleIdx)) {
|
||||
rfChoice = new Choice(this, grid.getFieldSlot(2, 1), STR_FLYSKY_PROTOCOLS, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_LR12,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].subType),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
rfChoice =
|
||||
new Choice(this, grid.getFieldSlot(2, 1),
|
||||
STR_FLYSKY_PROTOCOLS, 0, FLYSKY_SUBTYPE_AFHDS2A,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].subType),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
|
||||
if (moduleIdx == INTERNAL_MODULE) {
|
||||
g_model.moduleData[moduleIdx].subType = FLYSKY_SUBTYPE_AFHDS2A;
|
||||
rfChoice->setAvailableHandler(
|
||||
[](int v) { return v == FLYSKY_SUBTYPE_AFHDS2A; });
|
||||
} else {
|
||||
g_model.moduleData[moduleIdx].subType = FLYSKY_SUBTYPE_AFHDS3;
|
||||
rfChoice->setAvailableHandler(
|
||||
[](int v) { return v == FLYSKY_SUBTYPE_AFHDS3; });
|
||||
}
|
||||
|
||||
// RX options:
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_OPTIONS, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
|
||||
#if defined(AFHDS2)
|
||||
if (isModuleAFHDS2A(moduleIdx)) {
|
||||
// PPM / PWM
|
||||
new Choice(
|
||||
this, grid.getFieldSlot(2, 0), STR_FLYSKY_PULSE_PROTO, 0, 1,
|
||||
[=]() { return g_model.moduleData[moduleIdx].flysky.mode >> 1; },
|
||||
[=](int v) {
|
||||
g_model.moduleData[moduleIdx].flysky.mode =
|
||||
(g_model.moduleData[moduleIdx].flysky.mode & 1) |
|
||||
((v & 1) << 1);
|
||||
});
|
||||
// SBUS / iBUS
|
||||
new Choice(
|
||||
this, grid.getFieldSlot(2, 1), STR_FLYSKY_SERIAL_PROTO, 0, 1,
|
||||
[=]() { return g_model.moduleData[moduleIdx].flysky.mode & 1; },
|
||||
[=](int v) {
|
||||
g_model.moduleData[moduleIdx].flysky.mode =
|
||||
(g_model.moduleData[moduleIdx].flysky.mode & 2) | (v & 1);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
#if defined(AFHDS3)
|
||||
if (isModuleAFHDS3(moduleIdx)) {
|
||||
|
||||
// PPM / PWM
|
||||
new Choice(
|
||||
this, grid.getFieldSlot(2, 0), STR_FLYSKY_PULSE_PROTO, 0, 1,
|
||||
[=]() { return g_model.moduleData[moduleIdx].afhds3.mode >> 1; },
|
||||
[=](int v) {
|
||||
g_model.moduleData[moduleIdx].afhds3.mode =
|
||||
(g_model.moduleData[moduleIdx].afhds3.mode & 1) |
|
||||
((v & 1) << 1);
|
||||
});
|
||||
// SBUS / iBUS
|
||||
new Choice(
|
||||
this, grid.getFieldSlot(2, 1), STR_FLYSKY_SERIAL_PROTO, 0, 1,
|
||||
[=]() { return g_model.moduleData[moduleIdx].afhds3.mode & 1; },
|
||||
[=](int v) {
|
||||
g_model.moduleData[moduleIdx].afhds3.mode =
|
||||
(g_model.moduleData[moduleIdx].afhds3.mode & 2) | (v & 1);
|
||||
});
|
||||
|
||||
// TYPE
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_TYPE, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
|
||||
// This is chosen when binding (menu? see stdlcd/model_setup_afhds3.cpp)
|
||||
new StaticText(this, grid.getFieldSlot(),
|
||||
g_model.moduleData[moduleIdx].afhds3.telemetry
|
||||
? STR_AFHDS3_ONE_TO_ONE_TELEMETRY
|
||||
: TR_AFHDS3_ONE_TO_MANY,
|
||||
0, COLOR_THEME_PRIMARY1);
|
||||
|
||||
// Status
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_MODULE_STATUS, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(this, grid.getFieldSlot(), [=] {
|
||||
char msg[64] = "";
|
||||
getModuleStatusString(moduleIdx, msg);
|
||||
return std::string(msg);
|
||||
});
|
||||
|
||||
// Power source
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_AFHDS3_POWER_SOURCE,
|
||||
0, COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(this, grid.getFieldSlot(), [=] {
|
||||
char msg[64] = "";
|
||||
getModuleSyncStatusString(moduleIdx, msg);
|
||||
return std::string(msg);
|
||||
});
|
||||
|
||||
// RX Freq
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_AFHDS3_RX_FREQ, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
auto edit = new NumberEdit(
|
||||
this, grid.getFieldSlot(2, 0), MIN_FREQ, MAX_FREQ,
|
||||
GET_DEFAULT(g_model.moduleData[moduleIdx].afhds3.rxFreq()));
|
||||
edit->setSetValueHandler([=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].afhds3.setRxFreq(
|
||||
(uint16_t)newValue);
|
||||
});
|
||||
edit->setSuffix(STR_HZ);
|
||||
|
||||
// Module actual power
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_AFHDS3_ACTUAL_POWER,
|
||||
0, COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(this, grid.getFieldSlot(), [=] {
|
||||
char msg[64] = "";
|
||||
getStringAtIndex(msg, STR_AFHDS3_POWERS,
|
||||
actualAfhdsRunPower(moduleIdx));
|
||||
return std::string(msg);
|
||||
});
|
||||
|
||||
// Module power
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_RF_POWER, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new Choice(
|
||||
this, grid.getFieldSlot(2, 0), STR_AFHDS3_POWERS,
|
||||
afhds3::RUN_POWER::RUN_POWER_FIRST,
|
||||
afhds3::RUN_POWER::RUN_POWER_LAST,
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].afhds3.runPower));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(MULTIMODULE)
|
||||
else if (isModuleMultimodule(moduleIdx)) {
|
||||
Choice * mmSubProto = nullptr;
|
||||
@@ -1030,62 +1163,6 @@ class ModuleWindow : public FormGroup {
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.disableMapping));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AFHDS3)
|
||||
else if (isModuleAFHDS3(moduleIdx)) {
|
||||
rfChoice = new Choice(this, grid.getFieldSlot(2, 1), STR_AFHDS3_PROTOCOLS, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST,
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].subType));
|
||||
|
||||
// TYPE
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_TYPE, 0, COLOR_THEME_PRIMARY1);
|
||||
new StaticText(this, grid.getFieldSlot(),
|
||||
g_model.moduleData[EXTERNAL_MODULE].afhds3.telemetry ? STR_AFHDS3_ONE_TO_ONE_TELEMETRY : TR_AFHDS3_ONE_TO_MANY,
|
||||
0, COLOR_THEME_PRIMARY1);
|
||||
|
||||
// Status
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_MODULE_STATUS, 0, COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(this, grid.getFieldSlot(), [=] {
|
||||
char msg[64] = "";
|
||||
getModuleStatusString(moduleIdx, msg);
|
||||
return std::string(msg);
|
||||
});
|
||||
|
||||
|
||||
// Power source
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_AFHDS3_POWER_SOURCE, 0, COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(this, grid.getFieldSlot(), [=] {
|
||||
char msg[64] = "";
|
||||
getModuleSyncStatusString(moduleIdx, msg);
|
||||
return std::string(msg);
|
||||
});
|
||||
|
||||
// RX Freq
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_AFHDS3_RX_FREQ, 0, COLOR_THEME_PRIMARY1);
|
||||
auto edit = new NumberEdit(this, grid.getFieldSlot(2,0), MIN_FREQ, MAX_FREQ, GET_DEFAULT(g_model.moduleData[moduleIdx].afhds3.rxFreq()));
|
||||
edit->setSetValueHandler([=](int32_t newValue) {
|
||||
g_model.moduleData[EXTERNAL_MODULE].afhds3.setRxFreq((uint16_t)newValue);
|
||||
});
|
||||
edit->setSuffix(STR_HZ);
|
||||
|
||||
// Module actual power
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_AFHDS3_ACTUAL_POWER, 0, COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(this, grid.getFieldSlot(), [=] {
|
||||
char msg[64] = "";
|
||||
getStringAtIndex(msg, STR_AFHDS3_POWERS, actualAfhdsRunPower(moduleIdx));
|
||||
return std::string(msg);
|
||||
});
|
||||
|
||||
// Module power
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_RF_POWER, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(this, grid.getFieldSlot(2, 0), STR_AFHDS3_POWERS, afhds3::RUN_POWER::RUN_POWER_FIRST, afhds3::RUN_POWER::RUN_POWER_LAST,
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].afhds3.runPower));
|
||||
}
|
||||
#endif
|
||||
grid.nextLine();
|
||||
|
||||
@@ -1126,7 +1203,9 @@ class ModuleWindow : public FormGroup {
|
||||
// Module parameters
|
||||
|
||||
// Bind and Range buttons
|
||||
if (!isModuleRFAccess(moduleIdx) && (isModuleModelIndexAvailable(moduleIdx)|| isModuleBindRangeAvailable(moduleIdx))) {
|
||||
if (!isModuleRFAccess(moduleIdx) &&
|
||||
(isModuleModelIndexAvailable(moduleIdx) ||
|
||||
isModuleBindRangeAvailable(moduleIdx))) {
|
||||
uint8_t thirdColumn = 0;
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_RECEIVER, 0, COLOR_THEME_PRIMARY1);
|
||||
|
||||
@@ -1151,10 +1230,13 @@ class ModuleWindow : public FormGroup {
|
||||
bindButton = new TextButton(this, grid.getFieldSlot(2 + thirdColumn, 0 + thirdColumn), STR_MODULE_BIND);
|
||||
bindButton->setPressHandler([=]() -> uint8_t {
|
||||
if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK) {
|
||||
rangeButton->check(false);
|
||||
if (rangeButton) rangeButton->check(false);
|
||||
}
|
||||
if (moduleState[moduleIdx].mode == MODULE_MODE_BIND) {
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
#if defined(AFHDS2)
|
||||
if (isModuleFlySky(moduleIdx)) resetPulsesAFHDS2();
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(MULTIMODULE)
|
||||
@@ -1163,6 +1245,11 @@ class ModuleWindow : public FormGroup {
|
||||
}
|
||||
#endif
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_BIND;
|
||||
#if defined(AFHDS2)
|
||||
if (isModuleFlySky(moduleIdx)) {
|
||||
resetPulsesAFHDS2();
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1172,7 +1259,8 @@ class ModuleWindow : public FormGroup {
|
||||
bindButton->check(false);
|
||||
}
|
||||
#if defined(MULTIMODULE)
|
||||
if (isModuleMultimodule(moduleIdx) && getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) {
|
||||
if (isModuleMultimodule(moduleIdx) &&
|
||||
getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) {
|
||||
setMultiBindStatus(moduleIdx, MULTI_BIND_NONE);
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
bindButton->check(false);
|
||||
@@ -1180,8 +1268,11 @@ class ModuleWindow : public FormGroup {
|
||||
#endif
|
||||
});
|
||||
|
||||
rangeButton = new TextButton(this, grid.getFieldSlot(2 + thirdColumn, 1 + thirdColumn), STR_MODULE_RANGE);
|
||||
rangeButton->setPressHandler([=]() -> uint8_t {
|
||||
if (isModuleRangeAvailable(moduleIdx)) {
|
||||
rangeButton = new TextButton(
|
||||
this, grid.getFieldSlot(2 + thirdColumn, 1 + thirdColumn),
|
||||
STR_MODULE_RANGE);
|
||||
rangeButton->setPressHandler([=]() -> uint8_t {
|
||||
if (moduleState[moduleIdx].mode == MODULE_MODE_BIND) {
|
||||
bindButton->check(false);
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
@@ -1189,8 +1280,7 @@ class ModuleWindow : public FormGroup {
|
||||
if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK) {
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_RANGECHECK;
|
||||
auto rssiDialog = new DynamicMessageDialog(
|
||||
this, "Range Test",
|
||||
@@ -1207,7 +1297,8 @@ class ModuleWindow : public FormGroup {
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
grid.nextLine();
|
||||
|
||||
@@ -236,6 +236,8 @@ void RadioVersionPage::build(FormWindow * window)
|
||||
auto options = new OptionsText(window, grid.getFieldSlot(1,0));
|
||||
grid.nextLine(options->height() + 4);
|
||||
|
||||
//TODO: NV14 internal module version (NV14internalModuleFwVersion)
|
||||
|
||||
#if defined(PXX2)
|
||||
// Module and receivers versions
|
||||
auto moduleVersions = new TextButton(window, grid.getLineSlot(), STR_MODULES_RX_VERSION);
|
||||
|
||||
@@ -573,7 +573,7 @@ bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType)
|
||||
case MODULE_TYPE_ISRM_PXX2:
|
||||
case MODULE_TYPE_R9M_LITE_PXX2:
|
||||
case MODULE_TYPE_R9M_LITE_PRO_PXX2:
|
||||
case MODULE_TYPE_AFHDS3:
|
||||
case MODULE_TYPE_FLYSKY:
|
||||
return false;
|
||||
|
||||
case MODULE_TYPE_XJT_PXX1:
|
||||
@@ -628,7 +628,7 @@ bool isInternalModuleAvailable(int moduleType)
|
||||
}
|
||||
|
||||
#if (defined(AFHDS3) || defined(AFHDS2A)) && (defined(INTERNAL_MODULE_AFHDS2A) || defined(INTERNAL_MODULE_AFHDS3))
|
||||
if (moduleType == MODULE_TYPE_AFHDS3) {
|
||||
if (moduleType == MODULE_TYPE_FLYSKY) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -713,7 +713,7 @@ bool isExternalModuleAvailable(int moduleType)
|
||||
#endif
|
||||
|
||||
#if !defined(AFHDS3)
|
||||
if (moduleType == MODULE_TYPE_AFHDS3)
|
||||
if (moduleType == MODULE_TYPE_FLYSKY)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#define AFHDS2_PERIOD (2 * 1000) /* us */
|
||||
|
||||
struct FlySkySerialPulsesData {
|
||||
uint8_t pulses[64];
|
||||
uint8_t * ptr;
|
||||
|
||||
@@ -549,7 +549,7 @@ inline bool isSbus(uint8_t mode)
|
||||
|
||||
inline bool isPWM(uint8_t mode)
|
||||
{
|
||||
return mode < 2;
|
||||
return !(mode & 2);
|
||||
}
|
||||
|
||||
RUN_POWER PulsesData::getMaxRunPower() const
|
||||
@@ -604,7 +604,9 @@ bool PulsesData::syncSettings()
|
||||
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
|
||||
return true;
|
||||
}
|
||||
PULSE_MODE modelPulseMode = isPWM(moduleData->subType) ? PULSE_MODE::PWM_MODE : PULSE_MODE::PPM_MODE;
|
||||
PULSE_MODE modelPulseMode = isPWM(moduleData->afhds3.mode)
|
||||
? PULSE_MODE::PWM_MODE
|
||||
: PULSE_MODE::PPM_MODE;
|
||||
if (modelPulseMode != cfg.config.pulseMode) {
|
||||
cfg.config.pulseMode = modelPulseMode;
|
||||
TRACE("AFHDS3 PWM/PPM %d", modelPulseMode);
|
||||
@@ -613,7 +615,9 @@ bool PulsesData::syncSettings()
|
||||
return true;
|
||||
}
|
||||
|
||||
SERIAL_MODE modelSerialMode = isSbus(moduleData->subType) ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS;
|
||||
SERIAL_MODE modelSerialMode = isSbus(moduleData->afhds3.mode)
|
||||
? SERIAL_MODE::SBUS_MODE
|
||||
: SERIAL_MODE::IBUS;
|
||||
if (modelSerialMode != cfg.config.serialMode) {
|
||||
cfg.config.serialMode = modelSerialMode;
|
||||
TRACE("AFHDS3 IBUS/SBUS %d", modelSerialMode);
|
||||
@@ -660,9 +664,12 @@ void PulsesData::setConfigFromModel()
|
||||
cfg.config.emiStandard = EMI_STANDARD::FCC;
|
||||
cfg.config.telemetry = moduleData->afhds3.telemetry; //always use bidirectional mode
|
||||
cfg.config.pwmFreq = moduleData->afhds3.rxFreq();
|
||||
cfg.config.serialMode = isSbus(moduleData->subType) ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS;
|
||||
cfg.config.pulseMode = isPWM(moduleData->subType) ? PULSE_MODE::PWM_MODE : PULSE_MODE::PPM_MODE;
|
||||
//use max channels - because channel count can not be changed after bind
|
||||
cfg.config.serialMode = isSbus(moduleData->afhds3.mode)
|
||||
? SERIAL_MODE::SBUS_MODE
|
||||
: SERIAL_MODE::IBUS;
|
||||
cfg.config.pulseMode = isPWM(moduleData->afhds3.mode) ? PULSE_MODE::PWM_MODE
|
||||
: PULSE_MODE::PPM_MODE;
|
||||
// use max channels - because channel count can not be changed after bind
|
||||
cfg.config.channelCount = MAX_CHANNELS;
|
||||
cfg.config.failSafeTimout = moduleData->afhds3.failsafeTimeout;
|
||||
setFailSafe(cfg.config.failSafeMode);
|
||||
|
||||
@@ -0,0 +1,741 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Dedicate for FlySky NV14 board.
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
#include "flysky.h"
|
||||
#include "telemetry/flysky_nv14.h"
|
||||
|
||||
#define IS_VALID_COMMAND_ID(id) ((id) < CMD_LAST)
|
||||
|
||||
#ifndef custom_log
|
||||
#define custom_log
|
||||
#endif
|
||||
|
||||
// 0:OFF, 1:RF frame only, 2:TX frame only, 3:Both RF and TX frame
|
||||
enum DEBUG_RF_FRAME_PRINT_E {
|
||||
FRAME_PRINT_OFF = 0,
|
||||
RF_FRAME_ONLY = 1,
|
||||
TX_FRAME_ONLY = 2,
|
||||
BOTH_FRAME_PRINT = 3
|
||||
};
|
||||
|
||||
#define DEBUG_RF_FRAME_PRINT FRAME_PRINT_OFF
|
||||
//#define DEBUG_RF_FRAME_PRINT BOTH_FRAME_PRINT
|
||||
#define FLYSKY_MODULE_TIMEOUT 155 /* ms */
|
||||
#define FLYSKY_PERIOD 4 /*ms*/
|
||||
#define NUM_OF_NV14_CHANNELS (14)
|
||||
#define VALID_CH_DATA(v) ((v) > 900 && (v) < 2100)
|
||||
#define FAILSAVE_SEND_COUNTER_MAX (400)
|
||||
|
||||
#define gRomData g_model.moduleData[INTERNAL_MODULE].flysky
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
enum FlySkyBindState_E {
|
||||
BIND_LOW_POWER,
|
||||
BIND_NORMAL_POWER,
|
||||
BIND_EXIT,
|
||||
};
|
||||
|
||||
enum FlySkyRxPulse_E { FLYSKY_PWM, FLYSKY_PPM };
|
||||
|
||||
enum FlySkyRxPort_E { FLYSKY_IBUS, FLYSKY_SBUS };
|
||||
|
||||
enum FlySkyFirmwareType_E { FLYSKY_RX_FIRMWARE, FLYSKY_RF_FIRMWARE };
|
||||
enum FlySkyChannelDataType_E {
|
||||
FLYSKY_CHANNEL_DATA_NORMAL,
|
||||
FLYSKY_CHANNEL_DATA_FAILSAFE
|
||||
};
|
||||
|
||||
enum FlySkyPulseModeValue_E { PWM_IBUS, PWM_SBUS, PPM_IBUS, PPM_SBUS };
|
||||
|
||||
enum FlySkyPulseProtocol_E {
|
||||
FLYSKY_AFHDS1,
|
||||
FLYSKY_AFHDS2,
|
||||
FLYSKY_AFHDS2A,
|
||||
};
|
||||
|
||||
enum FlySkyModuleState_E {
|
||||
STATE_SET_TX_POWER = 0,
|
||||
STATE_INIT = 1,
|
||||
STATE_GET_FW_VERSION_INIT = 2,
|
||||
STATE_BIND = 3,
|
||||
STATE_SET_RECEIVER_ID = 4,
|
||||
STATE_SET_RX_PWM_PPM = 5,
|
||||
STATE_SET_RX_IBUS_SBUS = 6,
|
||||
STATE_SET_RX_FREQUENCY = 7,
|
||||
STATE_UPDATE_RF_FIRMWARE = 8,
|
||||
STATE_UPDATE_RX_FIRMWARE = 9,
|
||||
STATE_UPDATE_HALL_FIRMWARE = 10,
|
||||
STATE_UPDATE_RF_PROTOCOL = 11,
|
||||
STATE_GET_RECEIVER_CONFIG = 12,
|
||||
STATE_GET_RX_VERSION_INFO = 13,
|
||||
STATE_GET_RF_VERSION_INFO = 14,
|
||||
STATE_SET_RANGE_TEST = 15,
|
||||
STATE_RANGE_TEST_RUNNING = 16,
|
||||
STATE_IDLE = 17,
|
||||
STATE_DISCONNECT = 18,
|
||||
STATE_SEND_CHANNELS = 19,
|
||||
};
|
||||
|
||||
#define AfhdsPwmMode (gRomData.mode & 2 ? FLYSKY_PPM : FLYSKY_PWM)
|
||||
#define AfhdsIbusMode (gRomData.mode & 1 ? FLYSKY_SBUS : FLYSKY_IBUS)
|
||||
|
||||
struct rf_info_t {
|
||||
uint8_t bind_power;
|
||||
uint8_t protocol;
|
||||
// 0: normal, COMMAND_ID0C_UPDATE_RF_FIRMWARE or CMD_UPDATE_FIRMWARE_END
|
||||
uint8_t fw_state;
|
||||
};
|
||||
|
||||
// static STRUCT_HALL rxBuffer = {0};
|
||||
static uint32_t rfRxCount = 0;
|
||||
static uint8_t lastState = STATE_IDLE;
|
||||
static uint32_t set_loop_cnt = 0;
|
||||
|
||||
uint32_t NV14internalModuleFwVersion;
|
||||
|
||||
static rf_info_t rf_info = {
|
||||
.bind_power = BIND_LOW_POWER,
|
||||
.protocol = FLYSKY_AFHDS2A, // never updated currently
|
||||
.fw_state = 0,
|
||||
};
|
||||
|
||||
typedef struct __attribute__((packed)) rxParams {
|
||||
uint8_t outputMode;
|
||||
uint8_t outputSerialMode;
|
||||
uint16_t outputFreq;
|
||||
} rxParams;
|
||||
|
||||
typedef struct __attribute__((packed)) fwVersion {
|
||||
uint8_t target;
|
||||
uint32_t version;
|
||||
} fwVersion;
|
||||
|
||||
struct __attribute__((packed)) afhds2Resp {
|
||||
uint8_t startByte;
|
||||
uint8_t frame_number;
|
||||
uint8_t frame_type;
|
||||
uint8_t command_id;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
uint8_t emptyRxID[] = {0, 0, 0, 0};
|
||||
|
||||
void setFlyskyState(uint8_t state);
|
||||
void onFlySkyBindReceiver();
|
||||
void onFlySkyModuleSetPower(bool isPowerOn);
|
||||
void afhds2Command(uint8_t type, uint8_t cmd);
|
||||
void onFlySkyGetVersionInfoStart(uint8_t isRfTransfer);
|
||||
// void usbDownloadTransmit(uint8_t *buffer, uint32_t size);
|
||||
|
||||
// extern uint32_t NV14internalModuleFwVersion;
|
||||
|
||||
#define END 0xC0
|
||||
#define ESC 0xDB
|
||||
#define ESC_END 0xDC
|
||||
#define ESC_ESC 0xDD
|
||||
|
||||
#define FRAME_TYPE_REQUEST_ACK 0x01
|
||||
#define FRAME_TYPE_REQUEST_NACK 0x02
|
||||
#define FRAME_TYPE_ANSWER 0x10
|
||||
|
||||
enum FlySkyModuleCommandID {
|
||||
CMD_NONE=0,
|
||||
CMD_RF_INIT=1,
|
||||
CMD_BIND=2,
|
||||
CMD_SET_RECEIVER_ID=3,
|
||||
CMD_RF_GET_CONFIG=4,
|
||||
CMD_SEND_CHANNEL_DATA=5,
|
||||
CMD_RX_SENSOR_DATA=6,
|
||||
CMD_SET_RX_PWM_PPM=7,
|
||||
CMD_SET_RX_SERVO_FREQ=8,
|
||||
CMD_GET_VERSION_INFO=9,
|
||||
CMD_SET_RX_IBUS_SBUS=0xA,
|
||||
CMD_SET_RX_IBUS_SERVO_EXT=0xB,
|
||||
CMD_UPDATE_RF_FIRMWARE = 0x0C,
|
||||
CMD_SET_TX_POWER = 0x0D,
|
||||
CMD_SET_RF_PROTOCOL,
|
||||
CMD_TEST_RANGE,
|
||||
CMD_TEST_RF_RESERVED,
|
||||
CMD_UPDATE_RX_FIRMWARE = 0x20,
|
||||
CMD_LAST
|
||||
};
|
||||
|
||||
bool isFlySkyUsbDownload(void) { return rf_info.fw_state != 0; }
|
||||
|
||||
// void usbSetFrameTransmit(uint8_t packetID, uint8_t *dataBuf, uint32_t nBytes)
|
||||
// {
|
||||
// // send to host via usb
|
||||
// uint8_t *pt = (uint8_t*)&rxBuffer;
|
||||
// // rxBuffer.head = HALL_PROTOLO_HEAD;
|
||||
// rxBuffer.hallID.hall_Id.packetID = packetID;//0x08;
|
||||
// rxBuffer.hallID.hall_Id.senderID = 0x03;
|
||||
// rxBuffer.hallID.hall_Id.receiverID = 0x02;
|
||||
|
||||
// if ( packetID == 0x08 ) {
|
||||
// uint8_t fwVerision[40];
|
||||
// for(uint32_t idx = 40; idx > 0; idx--)
|
||||
// {
|
||||
// if ( idx <= nBytes ) {
|
||||
// fwVerision[idx-1] = dataBuf[idx-1];
|
||||
// }
|
||||
// else fwVerision[idx-1] = 0;
|
||||
// }
|
||||
// dataBuf = fwVerision;
|
||||
// nBytes = 40;
|
||||
// }
|
||||
|
||||
// rxBuffer.length = nBytes;
|
||||
|
||||
// TRACE_NOCRLF("\r\nToUSB: 55 %02X %02X ", rxBuffer.hallID.ID, nBytes);
|
||||
// for ( uint32_t idx = 0; idx < nBytes; idx++ )
|
||||
// {
|
||||
// rxBuffer.data[idx] = dataBuf[idx];
|
||||
// TRACE_NOCRLF("%02X ", rxBuffer.data[idx]);
|
||||
// }
|
||||
// #if !defined(SIMU)
|
||||
// uint16_t checkSum = calc_crc16(pt, rxBuffer.length+3);
|
||||
// TRACE(" CRC:%04X;", checkSum);
|
||||
|
||||
// pt[rxBuffer.length + 3] = checkSum & 0xFF;
|
||||
// pt[rxBuffer.length + 4] = checkSum >> 8;
|
||||
|
||||
// usbDownloadTransmit(pt, rxBuffer.length + 5);
|
||||
// #endif
|
||||
// }
|
||||
|
||||
void onFlySkyModuleSetPower(bool isPowerOn)
|
||||
{
|
||||
if (isPowerOn) {
|
||||
INTERNAL_MODULE_ON();
|
||||
resetPulsesAFHDS2();
|
||||
} else {
|
||||
moduleState[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
|
||||
INTERNAL_MODULE_OFF();
|
||||
}
|
||||
}
|
||||
|
||||
void setFlyskyState(uint8_t state) { intmodulePulsesData.flysky.state = state; }
|
||||
|
||||
void onFlySkyUsbDownloadStart(uint8_t fw_state) { rf_info.fw_state = fw_state; }
|
||||
|
||||
void onFlySkyGetVersionInfoStart(uint8_t isRfTransfer)
|
||||
{
|
||||
lastState = intmodulePulsesData.flysky.state;
|
||||
setFlyskyState(isRfTransfer ? STATE_GET_RF_VERSION_INFO
|
||||
: STATE_GET_RX_VERSION_INFO);
|
||||
}
|
||||
|
||||
inline void initFlySkyArray()
|
||||
{
|
||||
intmodulePulsesData.flysky.ptr = intmodulePulsesData.flysky.pulses;
|
||||
intmodulePulsesData.flysky.crc = 0;
|
||||
}
|
||||
|
||||
inline void putFlySkyByte(uint8_t byte)
|
||||
{
|
||||
if (END == byte) {
|
||||
*intmodulePulsesData.flysky.ptr++ = ESC;
|
||||
*intmodulePulsesData.flysky.ptr++ = ESC_END;
|
||||
} else if (ESC == byte) {
|
||||
*intmodulePulsesData.flysky.ptr++ = ESC;
|
||||
*intmodulePulsesData.flysky.ptr++ = ESC_ESC;
|
||||
} else {
|
||||
*intmodulePulsesData.flysky.ptr++ = byte;
|
||||
}
|
||||
}
|
||||
|
||||
inline void putFlySkyFrameByte(uint8_t byte)
|
||||
{
|
||||
intmodulePulsesData.flysky.crc += byte;
|
||||
putFlySkyByte(byte);
|
||||
}
|
||||
|
||||
inline void putFlySkyFrameCmd(uint8_t type, uint8_t cmd)
|
||||
{
|
||||
intmodulePulsesData.flysky.crc += type + cmd;
|
||||
putFlySkyByte(type);
|
||||
putFlySkyByte(cmd);
|
||||
}
|
||||
|
||||
inline void putFlySkyFrameBytes(uint8_t* data, int length)
|
||||
{
|
||||
for (int i = 0; i < length; i++) {
|
||||
intmodulePulsesData.flysky.crc += data[i];
|
||||
putFlySkyByte(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
inline void putFlySkyFrameHeader()
|
||||
{
|
||||
initFlySkyArray();
|
||||
*intmodulePulsesData.flysky.ptr++ = END;
|
||||
putFlySkyFrameByte(intmodulePulsesData.flysky.frame_index);
|
||||
}
|
||||
|
||||
inline void putFlySkyFrameFooter()
|
||||
{
|
||||
if (++intmodulePulsesData.flysky.frame_index == 0) {
|
||||
intmodulePulsesData.flysky.frame_index = 1;
|
||||
}
|
||||
putFlySkyByte(intmodulePulsesData.flysky.crc ^ 0xff);
|
||||
*intmodulePulsesData.flysky.ptr++ = END;
|
||||
}
|
||||
|
||||
void afhds2Command(uint8_t type, uint8_t cmd)
|
||||
{
|
||||
putFlySkyFrameHeader();
|
||||
putFlySkyFrameCmd(type, cmd);
|
||||
putFlySkyFrameFooter();
|
||||
}
|
||||
|
||||
inline void putFlySkySendChannelData()
|
||||
{
|
||||
uint16_t pulseValue = 0;
|
||||
uint8_t channels_start = g_model.moduleData[INTERNAL_MODULE].channelsStart;
|
||||
uint8_t channels_last =
|
||||
channels_start + 8 + g_model.moduleData[INTERNAL_MODULE].channelsCount;
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_NACK, CMD_SEND_CHANNEL_DATA);
|
||||
|
||||
if (moduleState[INTERNAL_MODULE].counter-- == 0) {
|
||||
moduleState[INTERNAL_MODULE].counter = FAILSAVE_SEND_COUNTER_MAX;
|
||||
putFlySkyFrameByte(FLYSKY_CHANNEL_DATA_FAILSAFE);
|
||||
putFlySkyFrameByte(channels_last - channels_start);
|
||||
for (uint8_t channel = channels_start; channel < channels_last; channel++) {
|
||||
if (g_model.moduleData[INTERNAL_MODULE].failsafeMode == FAILSAFE_CUSTOM) {
|
||||
int16_t failsafeValue = g_model.failsafeChannels[channel];
|
||||
pulseValue =
|
||||
limit<uint16_t>(0, 988 + ((failsafeValue + 1024) / 2), 0xfff);
|
||||
} else if (g_model.moduleData[INTERNAL_MODULE].failsafeMode ==
|
||||
FAILSAFE_HOLD) {
|
||||
// protocol uses hold by default
|
||||
pulseValue = 0xfff;
|
||||
} else {
|
||||
int16_t failsafeValue =
|
||||
-1024 + 2 * PPM_CH_CENTER(channel) - 2 * PPM_CENTER;
|
||||
pulseValue =
|
||||
limit<uint16_t>(0, 988 + ((failsafeValue + 1024) / 2), 0xfff);
|
||||
}
|
||||
putFlySkyFrameByte(pulseValue & 0xff);
|
||||
putFlySkyFrameByte(pulseValue >> 8);
|
||||
}
|
||||
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) {
|
||||
TRACE("------FAILSAFE------");
|
||||
}
|
||||
} else {
|
||||
putFlySkyFrameByte(FLYSKY_CHANNEL_DATA_NORMAL);
|
||||
putFlySkyFrameByte(channels_last - channels_start);
|
||||
for (uint8_t channel = channels_start; channel < channels_last; channel++) {
|
||||
int channelValue =
|
||||
channelOutputs[channel] + 2 * PPM_CH_CENTER(channel) - 2 * PPM_CENTER;
|
||||
pulseValue = limit<uint16_t>(0, 988 + ((channelValue + 1024) / 2), 0xfff);
|
||||
putFlySkyFrameByte(pulseValue & 0xff);
|
||||
putFlySkyFrameByte(pulseValue >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void putFlySkyUpdateFirmwareStart(uint8_t cmd)
|
||||
{
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, cmd);
|
||||
}
|
||||
|
||||
bool checkFlySkyFrameCrc(const uint8_t* ptr, uint8_t size)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
|
||||
for (uint8_t i = 0; i < size; i++) {
|
||||
crc += ptr[i];
|
||||
}
|
||||
|
||||
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) {
|
||||
if (ptr[2] != 0x06 || (set_loop_cnt++ % 50 == 0)) {
|
||||
TRACE_NOCRLF("RF(%0d): C0", INTMODULE_USART_AFHDS2_BAUDRATE);
|
||||
for (int idx = 0; idx <= size; idx++) {
|
||||
TRACE_NOCRLF(" %02X", ptr[idx]);
|
||||
}
|
||||
TRACE_NOCRLF(" C0;" CRLF);
|
||||
|
||||
if ((crc ^ 0xff) != ptr[size]) {
|
||||
TRACE("ErrorCRC %02X especting %02X", crc ^ 0xFF, ptr[size]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (crc ^ 0xff) == ptr[size];
|
||||
}
|
||||
|
||||
inline void debugFrame(const uint8_t* rxBuffer, uint8_t rxBufferCount)
|
||||
{
|
||||
// debug print the content of the packet
|
||||
char buffer[64 * 3];
|
||||
char* pos = buffer;
|
||||
if (rxBufferCount * 3 > sizeof(buffer)) rxBufferCount = 64;
|
||||
for (int i = 0; i < rxBufferCount; i++) {
|
||||
pos += snprintf(pos, buffer + sizeof(buffer) - pos, "%02X ", rxBuffer[i]);
|
||||
}
|
||||
(*pos) = 0;
|
||||
TRACE("count [%d] data: %s", rxBufferCount, buffer);
|
||||
}
|
||||
|
||||
inline void parseResponse()
|
||||
{
|
||||
afhds2Resp* resp =
|
||||
reinterpret_cast<afhds2Resp*>(intmodulePulsesData.flysky.telemetry);
|
||||
uint8_t dataLen = intmodulePulsesData.flysky.telemetry_index;
|
||||
|
||||
if (resp->startByte != END || dataLen < 2) return;
|
||||
|
||||
dataLen -= 2;
|
||||
if (!checkFlySkyFrameCrc(intmodulePulsesData.flysky.telemetry + 1, dataLen)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((moduleState[INTERNAL_MODULE].mode != MODULE_MODE_BIND) &&
|
||||
(resp->frame_type == FRAME_TYPE_ANSWER) &&
|
||||
((intmodulePulsesData.flysky.frame_index - 1) != resp->frame_number)) {
|
||||
return;
|
||||
} else if (resp->frame_type == FRAME_TYPE_REQUEST_ACK) {
|
||||
intmodulePulsesData.flysky.frame_index = resp->frame_number;
|
||||
}
|
||||
|
||||
debugFrame(&resp->command_id, dataLen - 2);
|
||||
switch (resp->command_id) {
|
||||
default:
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_NORMAL &&
|
||||
intmodulePulsesData.flysky.state >= STATE_IDLE) {
|
||||
setFlyskyState(STATE_SEND_CHANNELS);
|
||||
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY)
|
||||
TRACE("State back to channel data");
|
||||
}
|
||||
break;
|
||||
case CMD_RF_INIT:
|
||||
if (resp->value == 0x01) { // action only RF ready
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_BIND)
|
||||
setFlyskyState(STATE_BIND);
|
||||
else
|
||||
setFlyskyState(STATE_GET_FW_VERSION_INIT); // get version first
|
||||
} else {
|
||||
// Try one more time;
|
||||
resetPulsesAFHDS2();
|
||||
setFlyskyState(STATE_INIT);
|
||||
}
|
||||
break;
|
||||
case CMD_BIND: {
|
||||
if (resp->frame_type != FRAME_TYPE_ANSWER) {
|
||||
setFlyskyState(STATE_IDLE);
|
||||
return;
|
||||
}
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_BIND)
|
||||
moduleState[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
|
||||
*((uint32_t*)gRomData.rx_id) =
|
||||
*(reinterpret_cast<const uint32_t*>(&resp->value));
|
||||
g_model.header.modelId[INTERNAL_MODULE] = gRomData.rx_id[3];
|
||||
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY)
|
||||
TRACE("New Rx ID: %02X %02X %02X %02X", gRomData.rx_id[0],
|
||||
gRomData.rx_id[1], gRomData.rx_id[2], gRomData.rx_id[3]);
|
||||
SET_DIRTY();
|
||||
resetPulsesAFHDS2();
|
||||
setFlyskyState(STATE_INIT);
|
||||
break;
|
||||
}
|
||||
case CMD_RF_GET_CONFIG:
|
||||
setFlyskyState(STATE_GET_RECEIVER_CONFIG);
|
||||
intmodulePulsesData.flysky.timeout = FLYSKY_MODULE_TIMEOUT;
|
||||
break;
|
||||
case CMD_RX_SENSOR_DATA:
|
||||
flySkyNv14ProcessTelemetryPacket(&resp->value, dataLen - 3);
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_NORMAL &&
|
||||
intmodulePulsesData.flysky.state >= STATE_IDLE) {
|
||||
setFlyskyState(STATE_SEND_CHANNELS);
|
||||
}
|
||||
break;
|
||||
case CMD_SET_RECEIVER_ID: {
|
||||
// range check seems to be not working
|
||||
// it disconnects receiver
|
||||
// if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_RANGECHECK) {
|
||||
// setFlyskyState(STATE_SET_RANGE_TEST);
|
||||
//}
|
||||
// else
|
||||
setFlyskyState(STATE_SEND_CHANNELS);
|
||||
return;
|
||||
}
|
||||
case CMD_TEST_RANGE:
|
||||
if (moduleState[INTERNAL_MODULE].mode != MODULE_MODE_RANGECHECK)
|
||||
resetPulsesAFHDS2();
|
||||
else
|
||||
setFlyskyState(STATE_RANGE_TEST_RUNNING);
|
||||
break;
|
||||
case CMD_SET_TX_POWER:
|
||||
setFlyskyState(STATE_INIT);
|
||||
break;
|
||||
case CMD_SET_RX_PWM_PPM:
|
||||
setFlyskyState(STATE_SET_RX_IBUS_SBUS);
|
||||
break;
|
||||
case CMD_SET_RX_IBUS_SBUS:
|
||||
setFlyskyState(STATE_SET_RX_FREQUENCY);
|
||||
break;
|
||||
case CMD_SET_RX_SERVO_FREQ:
|
||||
setFlyskyState(STATE_SEND_CHANNELS);
|
||||
break;
|
||||
case CMD_UPDATE_RF_FIRMWARE: {
|
||||
rf_info.fw_state = STATE_UPDATE_RF_FIRMWARE;
|
||||
setFlyskyState(STATE_IDLE);
|
||||
break;
|
||||
}
|
||||
case CMD_GET_VERSION_INFO: {
|
||||
if (intmodulePulsesData.flysky.state == STATE_GET_FW_VERSION_INIT) {
|
||||
memcpy(&NV14internalModuleFwVersion, &resp->value + 1,
|
||||
sizeof(NV14internalModuleFwVersion));
|
||||
setFlyskyState(STATE_SET_RECEIVER_ID);
|
||||
break;
|
||||
}
|
||||
|
||||
// if (dataLen > 4) {
|
||||
// usbSetFrameTransmit(0x08, (uint8_t*) &resp->value + 1, dataLen - 4);
|
||||
// }
|
||||
|
||||
if (lastState == STATE_GET_RF_VERSION_INFO ||
|
||||
lastState == STATE_GET_RX_VERSION_INFO) {
|
||||
lastState = STATE_INIT;
|
||||
}
|
||||
setFlyskyState(lastState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isrxBufferMsgOK(void)
|
||||
{
|
||||
bool isMsgOK = (0 != rfRxCount);
|
||||
rfRxCount = 0;
|
||||
return isMsgOK && isFlySkyUsbDownload();
|
||||
}
|
||||
|
||||
void processInternalFlySkyTelemetryData(uint8_t byte)
|
||||
{
|
||||
// #if !defined(SIMU)
|
||||
// parseFlyskyData(&rxBuffer, byte);
|
||||
// #endif
|
||||
// if (rxBuffer.valid) {
|
||||
// rfRxCount++;
|
||||
// rxBuffer.valid = 0;
|
||||
// uint8_t *pt = (uint8_t*)&rxBuffer;
|
||||
// //rxBuffer.head = HALL_PROTOLO_HEAD;
|
||||
// pt[rxBuffer.length + 3] = rxBuffer.checkSum & 0xFF;
|
||||
// pt[rxBuffer.length + 4] = rxBuffer.checkSum >> 8;
|
||||
|
||||
// if((DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY)) {
|
||||
// TRACE("RF: %02X %02X %02X ...%04X; CRC:%04X", pt[0], pt[1], pt[2],
|
||||
// rxBuffer.checkSum, calc_crc16(pt, rxBuffer.length+3));
|
||||
// }
|
||||
|
||||
// //FW UPDATE done
|
||||
// if (0x01 == rxBuffer.length && (0x05 == rxBuffer.data[0] || 0x06 ==
|
||||
// rxBuffer.data[0])) {
|
||||
// setFlyskyState(STATE_INIT);
|
||||
// rf_info.fw_state = 0;
|
||||
// }
|
||||
// usbDownloadTransmit(pt, rxBuffer.length + 5);
|
||||
// }
|
||||
if (byte == END && intmodulePulsesData.flysky.telemetry_index > 0) {
|
||||
parseResponse();
|
||||
intmodulePulsesData.flysky.telemetry_index = 0;
|
||||
} else {
|
||||
if (byte == ESC) {
|
||||
intmodulePulsesData.flysky.esc_state = 1;
|
||||
} else {
|
||||
if (intmodulePulsesData.flysky.esc_state) {
|
||||
intmodulePulsesData.flysky.esc_state = 0;
|
||||
if (byte == ESC_END)
|
||||
byte = END;
|
||||
else if (byte == ESC_ESC)
|
||||
byte = ESC;
|
||||
}
|
||||
intmodulePulsesData.flysky
|
||||
.telemetry[intmodulePulsesData.flysky.telemetry_index++] = byte;
|
||||
if (intmodulePulsesData.flysky.telemetry_index >=
|
||||
sizeof(intmodulePulsesData.flysky.telemetry)) {
|
||||
// TODO buffer is full, log an error?
|
||||
intmodulePulsesData.flysky.telemetry_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resetPulsesAFHDS2()
|
||||
{
|
||||
NV14internalModuleFwVersion = 0;
|
||||
intmodulePulsesData.flysky.frame_index = 1;
|
||||
setFlyskyState(STATE_SET_TX_POWER);
|
||||
intmodulePulsesData.flysky.timeout = 0;
|
||||
intmodulePulsesData.flysky.esc_state = 0;
|
||||
uint16_t rx_freq = gRomData.rx_freq[0];
|
||||
rx_freq += (gRomData.rx_freq[1] * 256);
|
||||
if (50 > rx_freq || 400 < rx_freq) {
|
||||
gRomData.rx_freq[0] = 50;
|
||||
}
|
||||
}
|
||||
|
||||
void setupPulsesAFHDS2()
|
||||
{
|
||||
putFlySkyFrameHeader();
|
||||
if (intmodulePulsesData.flysky.state == STATE_DISCONNECT) {
|
||||
TRACE("STATE_DISCONNECT");
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_RECEIVER_ID);
|
||||
putFlySkyFrameBytes(emptyRxID, 4);
|
||||
} else if (intmodulePulsesData.flysky.state < STATE_SEND_CHANNELS) {
|
||||
if (++intmodulePulsesData.flysky.timeout >=
|
||||
FLYSKY_MODULE_TIMEOUT / FLYSKY_PERIOD) {
|
||||
intmodulePulsesData.flysky.timeout = 0;
|
||||
switch (intmodulePulsesData.flysky.state) {
|
||||
case STATE_INIT: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_RF_INIT);
|
||||
} break;
|
||||
case STATE_BIND: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_BIND);
|
||||
putFlySkyFrameByte(rf_info.bind_power);
|
||||
uint32_t txID =
|
||||
0; // internal module firmware does not allow changing TX id
|
||||
putFlySkyFrameBytes((uint8_t*)(&txID), 4);
|
||||
} break;
|
||||
case STATE_SET_RECEIVER_ID: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_RECEIVER_ID);
|
||||
putFlySkyFrameBytes(gRomData.rx_id, 4);
|
||||
} break;
|
||||
case STATE_GET_RECEIVER_CONFIG: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_ANSWER, CMD_RF_GET_CONFIG);
|
||||
putFlySkyFrameByte(AfhdsPwmMode); // 00:PWM, 01:PPM
|
||||
putFlySkyFrameByte(AfhdsIbusMode); // 00:I-BUS, 01:S-BUS
|
||||
putFlySkyFrameByte(
|
||||
gRomData.rx_freq[0] < 50
|
||||
? 50
|
||||
: gRomData.rx_freq[0]); // receiver servo freq bit[7:0]
|
||||
putFlySkyFrameByte(
|
||||
gRomData.rx_freq[1]); // receiver servo freq bit[15:8]
|
||||
setFlyskyState(STATE_INIT);
|
||||
} break;
|
||||
case STATE_SET_TX_POWER: {
|
||||
uint8_t power =
|
||||
moduleState[INTERNAL_MODULE].mode == MODULE_MODE_RANGECHECK ? 0
|
||||
: gRomData.rfPower ? 170
|
||||
: 90;
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_TX_POWER);
|
||||
putFlySkyFrameByte(power);
|
||||
} break;
|
||||
case STATE_SET_RANGE_TEST: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_TEST_RANGE);
|
||||
putFlySkyFrameByte(moduleState[INTERNAL_MODULE].mode ==
|
||||
MODULE_MODE_RANGECHECK);
|
||||
} break;
|
||||
case STATE_RANGE_TEST_RUNNING: {
|
||||
if (moduleState[INTERNAL_MODULE].mode != MODULE_MODE_RANGECHECK) {
|
||||
// this will send stop command
|
||||
setFlyskyState(STATE_SET_RANGE_TEST);
|
||||
}
|
||||
} break;
|
||||
case STATE_SET_RX_PWM_PPM: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_RX_PWM_PPM);
|
||||
putFlySkyFrameByte(AfhdsPwmMode); // 00:PWM, 01:PPM
|
||||
} break;
|
||||
case STATE_SET_RX_IBUS_SBUS: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_RX_IBUS_SBUS);
|
||||
putFlySkyFrameByte(AfhdsIbusMode); // 0x00:I-BUS, 0x01:S-BUS
|
||||
} break;
|
||||
case STATE_SET_RX_FREQUENCY: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_RX_SERVO_FREQ);
|
||||
putFlySkyFrameBytes(gRomData.rx_freq, 2);
|
||||
} break;
|
||||
case STATE_UPDATE_RF_PROTOCOL: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_SET_RF_PROTOCOL);
|
||||
putFlySkyFrameByte(
|
||||
rf_info.protocol); // 0x00:AFHDS1 0x01:AFHDS2 0x02:AFHDS2A
|
||||
} break;
|
||||
case STATE_UPDATE_RX_FIRMWARE: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_UPDATE_RX_FIRMWARE);
|
||||
} break;
|
||||
case STATE_UPDATE_RF_FIRMWARE: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_UPDATE_RF_FIRMWARE);
|
||||
} break;
|
||||
case STATE_GET_RX_VERSION_INFO: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_GET_VERSION_INFO);
|
||||
putFlySkyFrameByte(FLYSKY_RX_FIRMWARE);
|
||||
} break;
|
||||
case STATE_GET_FW_VERSION_INIT:
|
||||
case STATE_GET_RF_VERSION_INFO: {
|
||||
putFlySkyFrameCmd(FRAME_TYPE_REQUEST_ACK, CMD_GET_VERSION_INFO);
|
||||
putFlySkyFrameByte(FLYSKY_RF_FIRMWARE);
|
||||
} break;
|
||||
case STATE_IDLE:
|
||||
initFlySkyArray();
|
||||
break;
|
||||
default:
|
||||
setFlyskyState(STATE_INIT);
|
||||
initFlySkyArray();
|
||||
if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) {
|
||||
TRACE("State back to INIT\r\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
initFlySkyArray();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_BIND)
|
||||
moduleState[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
|
||||
putFlySkySendChannelData();
|
||||
}
|
||||
|
||||
putFlySkyFrameFooter();
|
||||
|
||||
if (intmodulePulsesData.flysky.state < STATE_SEND_CHANNELS) {
|
||||
// uint8_t size = intmodulePulsesData.flysky.ptr -
|
||||
// intmodulePulsesData.flysky.pulses;
|
||||
// debugFrame(intmodulePulsesData.flysky.pulses, size);
|
||||
}
|
||||
if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) {
|
||||
/* print each command, except channel data by interval */
|
||||
uint8_t* data = intmodulePulsesData.flysky.pulses;
|
||||
if (data[3] != CMD_SEND_CHANNEL_DATA || (set_loop_cnt++ % 100 == 0)) {
|
||||
uint8_t size = intmodulePulsesData.flysky.ptr - data;
|
||||
TRACE_NOCRLF("TX(State%0d)%0dB:", intmodulePulsesData.flysky.state, size);
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
TRACE_NOCRLF(" %02X", data[idx]);
|
||||
}
|
||||
TRACE_NOCRLF(";" CRLF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void usbDownloadTransmit(uint8_t *buffer, uint32_t size)
|
||||
// {
|
||||
// if (USB_SERIAL_MODE != getSelectedUsbMode()) return;
|
||||
// buffer[0] = HALL_PROTOLO_HEAD;
|
||||
// for (uint32_t idx = 0; idx < size; idx++)
|
||||
// {
|
||||
// #if !defined(SIMU)
|
||||
// usbSerialPutc(buffer[idx]);
|
||||
// #endif
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Dedicate for FlySky NV14 board.
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define INTMODULE_USART_AFHDS2_BAUDRATE 921600
|
||||
|
||||
void setupPulsesAFHDS2();
|
||||
void resetPulsesAFHDS2();
|
||||
|
||||
void processInternalFlySkyTelemetryData(uint8_t byte);
|
||||
@@ -37,8 +37,7 @@ enum ModuleType {
|
||||
MODULE_TYPE_R9M_LITE_PRO_PXX2,
|
||||
MODULE_TYPE_SBUS,
|
||||
MODULE_TYPE_XJT_LITE_PXX2,
|
||||
MODULE_TYPE_AFHDS3, //no more protocols possible because of 4 bits value
|
||||
//MODULE_TYPE_AFHDS2A,
|
||||
MODULE_TYPE_FLYSKY, //no more protocols possible because of 4 bits value
|
||||
MODULE_TYPE_COUNT,
|
||||
MODULE_TYPE_MAX = MODULE_TYPE_COUNT - 1
|
||||
};
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "libopenui/src/bitfield.h"
|
||||
#include "definitions.h"
|
||||
#include "opentx_helpers.h"
|
||||
#include "telemetry/telemetry.h"
|
||||
#include "storage/storage.h"
|
||||
#include "globals.h"
|
||||
|
||||
@@ -35,6 +34,67 @@
|
||||
#define CROSSFIRE_CHANNELS_COUNT 16
|
||||
#define GHOST_CHANNELS_COUNT 16
|
||||
|
||||
#if defined (MULTIMODULE)
|
||||
#define IS_D16_MULTI(module) \
|
||||
(((g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_FRSKY) && \
|
||||
(g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16 || \
|
||||
g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH || \
|
||||
g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT || \
|
||||
g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH || \
|
||||
g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_CLONED)) || \
|
||||
(g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_FRSKYX2))
|
||||
|
||||
#define IS_R9_MULTI(module) \
|
||||
(g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_FRSKY_R9)
|
||||
|
||||
#define IS_HOTT_MULTI(module) \
|
||||
(g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT)
|
||||
|
||||
#define IS_CONFIG_MULTI(module) \
|
||||
(g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_CONFIG)
|
||||
|
||||
#define IS_DSM_MULTI(module) \
|
||||
(g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2)
|
||||
|
||||
#define IS_RX_MULTI(module) \
|
||||
((g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_AFHDS2A_RX) || \
|
||||
(g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_FRSKYX_RX) || \
|
||||
(g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_BAYANG_RX) || \
|
||||
(g_model.moduleData[module].getMultiProtocol() == \
|
||||
MODULE_SUBTYPE_MULTI_DSM_RX))
|
||||
|
||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||
#define IS_FRSKY_SPORT_PROTOCOL() \
|
||||
(telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || \
|
||||
(telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && \
|
||||
(IS_D16_MULTI(INTERNAL_MODULE) || IS_D16_MULTI(EXTERNAL_MODULE) || \
|
||||
IS_R9_MULTI(INTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE))))
|
||||
#else
|
||||
#define IS_FRSKY_SPORT_PROTOCOL() \
|
||||
(telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || \
|
||||
(telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && \
|
||||
(IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE))))
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define IS_D16_MULTI(module) false
|
||||
#define IS_R9_MULTI(module) false
|
||||
#define IS_HOTT_MULTI(module) false
|
||||
#define IS_CONFIG_MULTI(module) false
|
||||
#define IS_DSM_MULTI(module) false
|
||||
#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
|
||||
#define IS_RX_MULTI(module) false
|
||||
#endif
|
||||
|
||||
#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM)
|
||||
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
// When using packed, the pointer in here end up not being aligned, which clang and gcc complain about
|
||||
// Keep the order of the fields that the so that the size stays small
|
||||
@@ -101,6 +161,11 @@ inline bool isModuleTypeXJT(uint8_t type)
|
||||
return type == MODULE_TYPE_XJT_PXX1 || type == MODULE_TYPE_XJT_LITE_PXX2;
|
||||
}
|
||||
|
||||
inline bool isModuleNone(uint8_t idx)
|
||||
{
|
||||
return g_model.moduleData[idx].type == MODULE_TYPE_NONE;
|
||||
}
|
||||
|
||||
inline bool isModuleXJT(uint8_t idx)
|
||||
{
|
||||
return isModuleTypeXJT(g_model.moduleData[idx].type);
|
||||
@@ -322,7 +387,7 @@ inline bool isModuleSBUS(uint8_t moduleIdx)
|
||||
inline bool isModuleFlySky(uint8_t idx)
|
||||
{
|
||||
return
|
||||
(g_model.moduleData[idx].type == MODULE_TYPE_AFHDS3);
|
||||
(g_model.moduleData[idx].type == MODULE_TYPE_FLYSKY);
|
||||
}
|
||||
|
||||
inline bool isModuleAFHDS2A(uint8_t idx)
|
||||
@@ -524,8 +589,8 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS3)
|
||||
if (isModuleAFHDS3(moduleIdx))
|
||||
#if defined(AFHDS3) || defined(AFHDS2)
|
||||
if (isModuleFlySky(moduleIdx))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -537,12 +602,16 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx)
|
||||
|
||||
inline bool isModuleBindRangeAvailable(uint8_t moduleIdx)
|
||||
{
|
||||
return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx) || isModuleAFHDS3(moduleIdx);
|
||||
return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) ||
|
||||
isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx) ||
|
||||
isModuleFlySky(moduleIdx);
|
||||
}
|
||||
|
||||
inline bool isModuleRangeAvailable(uint8_t moduleIdx)
|
||||
{
|
||||
return isModuleBindRangeAvailable(moduleIdx) && !IS_RX_MULTI(moduleIdx);
|
||||
return isModuleBindRangeAvailable(moduleIdx)
|
||||
&& !IS_RX_MULTI(moduleIdx)
|
||||
&& !isModuleFlySky(moduleIdx);
|
||||
}
|
||||
|
||||
constexpr uint8_t MAX_RXNUM = 63;
|
||||
@@ -595,6 +664,18 @@ inline bool isBindCh9To16Allowed(uint8_t moduleIndex)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
inline bool isSportLineUsedByInternalModule()
|
||||
{
|
||||
return g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT_PXX1;
|
||||
}
|
||||
#else
|
||||
inline bool isSportLineUsedByInternalModule()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool isTelemAllowedOnBind(uint8_t moduleIndex)
|
||||
{
|
||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||
@@ -700,8 +781,10 @@ inline void setModuleType(uint8_t moduleIdx, uint8_t moduleType)
|
||||
moduleData.sbus.refreshRate = -31;
|
||||
else if (moduleData.type == MODULE_TYPE_PPM)
|
||||
setDefaultPpmFrameLength(moduleIdx);
|
||||
else if (moduleData.type == MODULE_TYPE_AFHDS3)
|
||||
else if (moduleData.type == MODULE_TYPE_FLYSKY) {
|
||||
// TODO: what if AFHDS2A
|
||||
resetAfhds3Options(moduleIdx);
|
||||
}
|
||||
else
|
||||
resetAccessAuthenticationCount();
|
||||
}
|
||||
@@ -760,20 +843,4 @@ inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max)
|
||||
}
|
||||
#endif
|
||||
|
||||
inline const char * getRssiLabel()
|
||||
{
|
||||
#if defined(MULTIMODULE)
|
||||
if (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FS_AFHDS2A
|
||||
|| g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT)) {
|
||||
return "RQly";
|
||||
}
|
||||
#endif
|
||||
#if defined(GHOST)
|
||||
if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) {
|
||||
return "RQly";
|
||||
}
|
||||
#endif
|
||||
return "RSSI";
|
||||
}
|
||||
|
||||
#endif // _MODULES_HELPERS_H_
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "io/frsky_pxx2.h"
|
||||
#include "pulses/pxx2.h"
|
||||
#include "mixer_scheduler.h"
|
||||
|
||||
#include "io/frsky_pxx2.h"
|
||||
#include "io/multi_protolist.h"
|
||||
#include "pulses/pxx2.h"
|
||||
#include "pulses/flysky.h"
|
||||
|
||||
uint8_t s_pulses_paused = 0;
|
||||
ModuleState moduleState[NUM_MODULES];
|
||||
@@ -189,7 +191,7 @@ uint8_t getRequiredProtocol(uint8_t module)
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS3) || defined(AFHDS2)
|
||||
case MODULE_TYPE_AFHDS3:
|
||||
case MODULE_TYPE_FLYSKY:
|
||||
if (isModuleAFHDS3(module)) {
|
||||
protocol = PROTOCOL_CHANNELS_AFHDS3;
|
||||
} else if (isModuleAFHDS2A(module)) {
|
||||
@@ -489,9 +491,11 @@ static void enablePulsesInternalModule(uint8_t protocol)
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A:
|
||||
/* extmodulePulsesData.afhds2.init(INTERNAL_MODULE);
|
||||
extmoduleSerialStart();*/
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 2 * 1000 /* us */);
|
||||
resetPulsesAFHDS2();
|
||||
intmoduleSerialStart(INTMODULE_USART_AFHDS2_BAUDRATE, true,
|
||||
USART_Parity_No, USART_StopBits_1,
|
||||
USART_WordLength_8b);
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, AFHDS2_PERIOD);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -544,6 +548,19 @@ bool setupPulsesInternalModule(uint8_t protocol)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A:
|
||||
{
|
||||
ModuleSyncStatus& status = getModuleSyncStatus(INTERNAL_MODULE);
|
||||
mixerSchedulerSetPeriod(
|
||||
INTERNAL_MODULE,
|
||||
status.isValid() ? status.getAdjustedRefreshRate() : AFHDS2_PERIOD);
|
||||
status.invalidate();
|
||||
setupPulsesAFHDS2();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "pxx2.h"
|
||||
#include "multi.h"
|
||||
#include "afhds3.h"
|
||||
#include "afhds2.h"
|
||||
#include "modules_helpers.h"
|
||||
#include "ff.h"
|
||||
|
||||
@@ -266,6 +267,10 @@ union InternalModulePulsesData {
|
||||
Pxx2Pulses pxx2;
|
||||
#endif
|
||||
|
||||
#if defined(INTMODULE_USART) && defined(AFHDS2)
|
||||
FlySkySerialPulsesData flysky;
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE) //&& defined(INTMODULE_USART)
|
||||
UartMultiPulses multi;
|
||||
#endif
|
||||
|
||||
@@ -159,9 +159,11 @@ endif()
|
||||
if(MULTIMODULE OR AFHDS3)
|
||||
set(SRC ${SRC} telemetry/flysky_ibus.cpp)
|
||||
endif()
|
||||
|
||||
if(AFHDS2)
|
||||
add_definitions(-DAFHDS2)
|
||||
set(SRC ${SRC} telemetry/flysky_nv14.cpp)
|
||||
set(PULSES_SRC ${PULSES_SRC} flysky.cpp)
|
||||
endif()
|
||||
|
||||
if(AFHDS3)
|
||||
|
||||
@@ -187,5 +187,13 @@ void intmoduleSendNextFrame()
|
||||
intmoduleSendBuffer(intmodulePulsesData.multi.getData(), intmodulePulsesData.multi.getSize());
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A: {
|
||||
uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses;
|
||||
uint16_t size = intmodulePulsesData.flysky.ptr - data;
|
||||
intmoduleSendBuffer(data, size);
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,9 @@ if(NOT UNEXPECTED_SHUTDOWN)
|
||||
endif()
|
||||
|
||||
set(AFHDS2 ON)
|
||||
set(AFHDS3 ON)
|
||||
|
||||
# disable for now as it crashes on radio
|
||||
#set(AFHDS3 ON)
|
||||
|
||||
include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts)
|
||||
|
||||
|
||||
@@ -413,7 +413,6 @@
|
||||
#define INTMODULE_USART_IRQHandler UART7_IRQHandler
|
||||
#define INTMODULE_DMA_STREAM DMA1_Stream1
|
||||
#define INTMODULE_DMA_STREAM_IRQ DMA1_Stream1_IRQn
|
||||
#define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler
|
||||
#define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF1
|
||||
#define INTMODULE_DMA_CHANNEL DMA_Channel_5
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ bool isModuleSynchronous(uint8_t moduleIdx)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE:
|
||||
case PROTOCOL_CHANNELS_GHOST:
|
||||
case PROTOCOL_CHANNELS_AFHDS3:
|
||||
case PROTOCOL_CHANNELS_AFHDS2A:
|
||||
case PROTOCOL_CHANNELS_NONE:
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
|
||||
@@ -21,6 +21,46 @@
|
||||
#include "opentx.h"
|
||||
#include "flysky_nv14.h"
|
||||
|
||||
enum FlySkySensorType_E {
|
||||
FLYSKY_SENSOR_RX_VOLTAGE=0,
|
||||
FLYSKY_SENSOR_RX_SIGNAL,
|
||||
FLYSKY_SENSOR_RX_RSSI,
|
||||
FLYSKY_SENSOR_RX_NOISE,
|
||||
FLYSKY_SENSOR_RX_SNR,
|
||||
|
||||
FLYSKY_SENSOR_TEMP,
|
||||
FLYSKY_SENSOR_EXT_VOLTAGE,
|
||||
FLYSKY_SENSOR_MOTO_RPM,
|
||||
FLYSKY_SENSOR_PRESSURE,
|
||||
FLYSKY_SENSOR_GPS
|
||||
};
|
||||
|
||||
typedef struct FLYSKY_GPS_INFO_S {
|
||||
uint8_t position_fix;
|
||||
uint8_t satell_cnt;
|
||||
uint8_t latitude[4];
|
||||
uint8_t longtitude[4];
|
||||
uint8_t altitude[4];
|
||||
uint8_t g_speed[2];
|
||||
uint8_t direction[2];
|
||||
} gps_info_t;
|
||||
|
||||
typedef struct FLYSKY_SENSOR_DATA_S {
|
||||
uint8_t sensor_type;
|
||||
uint8_t sensor_id;
|
||||
uint8_t voltage[2];
|
||||
uint8_t signal;
|
||||
uint8_t rssi[2];
|
||||
uint8_t noise[2];
|
||||
uint8_t snr[2];
|
||||
uint8_t temp[2];
|
||||
uint8_t ext_voltage[2];
|
||||
uint8_t moto_rpm[2];
|
||||
uint8_t pressure_value[2];
|
||||
gps_info_t gps_info;
|
||||
} rx_sensor_t;
|
||||
|
||||
|
||||
#define FLYSKY_FIXED_RX_VOLTAGE (uint8_t)(FLYSKY_SENSOR_RX_VOLTAGE + (uint8_t)0xA0)
|
||||
|
||||
#define MIN_SNR 8
|
||||
@@ -43,7 +83,6 @@ struct FlyskyNv14Sensor {
|
||||
const bool issigned;
|
||||
};
|
||||
|
||||
|
||||
union nv14SensorData {
|
||||
uint8_t UINT8;
|
||||
uint16_t UINT16;
|
||||
@@ -51,8 +90,6 @@ union nv14SensorData {
|
||||
uint32_t UINT32;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const FlyskyNv14Sensor Nv14Sensor[]=
|
||||
{
|
||||
{FLYSKY_FIXED_RX_VOLTAGE, 0, STR_SENSOR_A3, UNIT_VOLTS, 2, 0, 2, false},
|
||||
@@ -64,8 +101,8 @@ const FlyskyNv14Sensor Nv14Sensor[]=
|
||||
{FLYSKY_SENSOR_TEMP, 0, STR_SENSOR_TEMP1, UNIT_CELSIUS, 1, 0, 2, true},
|
||||
{FLYSKY_SENSOR_EXT_VOLTAGE,0, STR_SENSOR_A3, UNIT_VOLTS, 2, 0, 2, false},
|
||||
{FLYSKY_SENSOR_MOTO_RPM, 0, STR_SENSOR_RPM, UNIT_RPMS, 0, 0, 2, false},
|
||||
{FLYSKY_SENSOR_PRESURRE, 0, STR_SENSOR_PRES, UNIT_RAW, 1, 0, 2, false},
|
||||
{FLYSKY_SENSOR_PRESURRE, 1, STR_SENSOR_ALT, UNIT_METERS, 0, 0, 2, true},
|
||||
{FLYSKY_SENSOR_PRESSURE, 0, STR_SENSOR_PRES, UNIT_RAW, 1, 0, 2, false},
|
||||
{FLYSKY_SENSOR_PRESSURE, 1, STR_SENSOR_ALT, UNIT_METERS, 0, 0, 2, true},
|
||||
{FLYSKY_SENSOR_GPS, 1, STR_SENSOR_SATELLITES, UNIT_RAW, 0, 0, 1, false},
|
||||
{FLYSKY_SENSOR_GPS, 2, STR_SENSOR_GPS, UNIT_GPS_LATITUDE, 0, 1, 4, true},
|
||||
{FLYSKY_SENSOR_GPS, 3, STR_SENSOR_GPS, UNIT_GPS_LONGITUDE, 0, 5, 4, true},
|
||||
@@ -77,25 +114,32 @@ const FlyskyNv14Sensor Nv14Sensor[]=
|
||||
|
||||
FlyskyNv14Sensor defaultNv14Sensor = {0, 0, "UNKNOWN", UNIT_RAW, 0, 0, 2, false};
|
||||
|
||||
const signed short tAltitude[225]=
|
||||
{
|
||||
20558, 20357, 20158, 19962, 19768, 19576, 19387, 19200, 19015, 18831, 18650, 18471, 18294, 18119, 17946, 17774,
|
||||
17604, 17436, 17269, 17105, 16941, 16780, 16619, 16461, 16304, 16148, 15993, 15841, 15689, 15539, 15390, 15242,
|
||||
15096, 14950, 14806, 14664, 14522, 14381, 14242, 14104, 13966, 13830, 13695, 13561, 13428, 13296, 13165, 13035,
|
||||
12906, 12777, 12650, 12524, 12398, 12273, 12150, 12027, 11904, 11783, 11663, 11543, 11424, 11306, 11189, 11072,
|
||||
10956, 10841, 10726, 10613, 10500, 10387, 10276, 10165, 10054, 9945, 9836, 9727, 9620, 9512, 9406, 9300,
|
||||
9195, 9090, 8986, 8882, 8779, 8677, 8575, 8474, 8373, 8273, 8173, 8074, 7975, 7877, 7779, 7682,
|
||||
7585, 7489, 7394, 7298, 7204, 7109, 7015, 6922, 6829, 6737, 6645, 6553, 6462, 6371, 6281, 6191,
|
||||
6102, 6012, 5924, 5836, 5748, 5660, 5573, 5487, 5400, 5314, 5229, 5144, 5059, 4974, 4890, 4807,
|
||||
4723, 4640, 4557, 4475, 4393, 4312, 4230, 4149, 4069, 3988, 3908, 3829, 3749, 3670, 3591, 3513,
|
||||
3435, 3357, 3280, 3202, 3125, 3049, 2972, 2896, 2821, 2745, 2670, 2595, 2520, 2446, 2372, 2298,
|
||||
2224, 2151, 2078, 2005, 1933, 1861, 1789, 1717, 1645, 1574, 1503, 1432, 1362, 1292, 1222, 1152,
|
||||
1082, 1013, 944, 875, 806, 738, 670, 602, 534, 467, 399, 332, 265, 199, 132, 66,
|
||||
0, -66, -131, -197, -262, -327, -392, -456, -521, -585, -649, -713, -776, -840, -903, -966,
|
||||
-1029,-1091, -1154, -1216, -1278, -1340, -1402, -1463, -1525, -1586, -1647, -1708, -1769, -1829, -1889, -1950,
|
||||
-2010
|
||||
const signed short tAltitude[225] = {
|
||||
20558, 20357, 20158, 19962, 19768, 19576, 19387, 19200, 19015, 18831, 18650,
|
||||
18471, 18294, 18119, 17946, 17774, 17604, 17436, 17269, 17105, 16941, 16780,
|
||||
16619, 16461, 16304, 16148, 15993, 15841, 15689, 15539, 15390, 15242, 15096,
|
||||
14950, 14806, 14664, 14522, 14381, 14242, 14104, 13966, 13830, 13695, 13561,
|
||||
13428, 13296, 13165, 13035, 12906, 12777, 12650, 12524, 12398, 12273, 12150,
|
||||
12027, 11904, 11783, 11663, 11543, 11424, 11306, 11189, 11072, 10956, 10841,
|
||||
10726, 10613, 10500, 10387, 10276, 10165, 10054, 9945, 9836, 9727, 9620,
|
||||
9512, 9406, 9300, 9195, 9090, 8986, 8882, 8779, 8677, 8575, 8474,
|
||||
8373, 8273, 8173, 8074, 7975, 7877, 7779, 7682, 7585, 7489, 7394,
|
||||
7298, 7204, 7109, 7015, 6922, 6829, 6737, 6645, 6553, 6462, 6371,
|
||||
6281, 6191, 6102, 6012, 5924, 5836, 5748, 5660, 5573, 5487, 5400,
|
||||
5314, 5229, 5144, 5059, 4974, 4890, 4807, 4723, 4640, 4557, 4475,
|
||||
4393, 4312, 4230, 4149, 4069, 3988, 3908, 3829, 3749, 3670, 3591,
|
||||
3513, 3435, 3357, 3280, 3202, 3125, 3049, 2972, 2896, 2821, 2745,
|
||||
2670, 2595, 2520, 2446, 2372, 2298, 2224, 2151, 2078, 2005, 1933,
|
||||
1861, 1789, 1717, 1645, 1574, 1503, 1432, 1362, 1292, 1222, 1152,
|
||||
1082, 1013, 944, 875, 806, 738, 670, 602, 534, 467, 399,
|
||||
332, 265, 199, 132, 66, 0, -66, -131, -197, -262, -327,
|
||||
-392, -456, -521, -585, -649, -713, -776, -840, -903, -966, -1029,
|
||||
-1091, -1154, -1216, -1278, -1340, -1402, -1463, -1525, -1586, -1647, -1708,
|
||||
-1769, -1829, -1889, -1950, -2010
|
||||
};
|
||||
signed short CalculateAltitude( unsigned int Pressure, unsigned int SeaLevelPressure )
|
||||
|
||||
signed short CalculateAltitude(unsigned int Pressure,
|
||||
unsigned int SeaLevelPressure)
|
||||
{
|
||||
unsigned int Index;
|
||||
signed int Altitude1;
|
||||
@@ -103,91 +147,104 @@ signed short CalculateAltitude( unsigned int Pressure, unsigned int SeaLevelPres
|
||||
unsigned int Decimal;
|
||||
unsigned long Ratio;
|
||||
|
||||
Ratio = ( ( ( unsigned long long ) Pressure << 16 ) + ( SeaLevelPressure / 2 ) ) / SeaLevelPressure;
|
||||
if( Ratio < ( ( 1 << 16 ) * 250 / 1000 ) )// 0.250 inclusive
|
||||
{
|
||||
Ratio = ( 1 << 16 ) * 250 / 1000;
|
||||
}
|
||||
else if( Ratio > ( 1 << 16 ) * 1125 / 1000 - 1 ) // 1.125 non-inclusive
|
||||
{
|
||||
Ratio = ( 1 << 16 ) * 1125 / 1000 - 1;
|
||||
Ratio = (((unsigned long long)Pressure << 16) + (SeaLevelPressure / 2)) /
|
||||
SeaLevelPressure;
|
||||
|
||||
if (Ratio < ((1 << 16) * 250 / 1000)) { // 0.250 inclusive
|
||||
Ratio = (1 << 16) * 250 / 1000;
|
||||
} else if (Ratio > (1 << 16) * 1125 / 1000 - 1) { // 1.125 non-inclusive
|
||||
Ratio = (1 << 16) * 1125 / 1000 - 1;
|
||||
}
|
||||
|
||||
Ratio -= ( 1 << 16 ) * 250 / 1000; // from 0.000 (inclusive) to 0.875 (non-inclusive)
|
||||
// from 0.000 (inclusive) to 0.875 (non-inclusive)
|
||||
Ratio -= (1 << 16) * 250 / 1000;
|
||||
Index = Ratio >> 8;
|
||||
Decimal = Ratio & ( ( 1 << 8 ) - 1 );
|
||||
Decimal = Ratio & ((1 << 8) - 1);
|
||||
Altitude1 = tAltitude[Index];
|
||||
Altitude2 = Altitude1 - tAltitude[Index + 1];
|
||||
Altitude1 = Altitude1 - ( Altitude2 * Decimal + ( 1 << 7 ) ) / ( 1 << 8 );
|
||||
if( Altitude1 >= 0 )
|
||||
{
|
||||
return( ( Altitude1 + 1 ) / 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( ( Altitude1 - 1 ) / 2 );
|
||||
Altitude1 = Altitude1 - (Altitude2 * Decimal + (1 << 7)) / (1 << 8);
|
||||
if (Altitude1 >= 0) {
|
||||
return ((Altitude1 + 1) / 2);
|
||||
} else {
|
||||
return ((Altitude1 - 1) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
const FlyskyNv14Sensor* getFlyskyNv14Sensor(uint16_t id, uint8_t subId)
|
||||
{
|
||||
for(unsigned index = 0; index < *(&Nv14Sensor + 1) - Nv14Sensor; index++ ){
|
||||
for (unsigned index = 0; index < *(&Nv14Sensor + 1) - Nv14Sensor; index++) {
|
||||
if (Nv14Sensor[index].id == id && Nv14Sensor[index].subId == subId) {
|
||||
return &Nv14Sensor[index];
|
||||
}
|
||||
}
|
||||
return &defaultNv14Sensor;
|
||||
return &defaultNv14Sensor;
|
||||
}
|
||||
|
||||
void flySkyNv14SetDefault(int index, uint8_t id, uint8_t subId, uint8_t instance)
|
||||
void flySkyNv14SetDefault(int index, uint8_t id, uint8_t subId,
|
||||
uint8_t instance)
|
||||
{
|
||||
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index];
|
||||
telemetrySensor.id = id;
|
||||
telemetrySensor.subId = subId;
|
||||
telemetrySensor.instance = instance;
|
||||
const FlyskyNv14Sensor* sensor = getFlyskyNv14Sensor(id, subId);
|
||||
telemetrySensor.init(sensor->name, sensor->unit, sensor->precision);
|
||||
storageDirty(EE_MODEL);
|
||||
TelemetrySensor& telemetrySensor = g_model.telemetrySensors[index];
|
||||
telemetrySensor.id = id;
|
||||
telemetrySensor.subId = subId;
|
||||
telemetrySensor.instance = instance;
|
||||
const FlyskyNv14Sensor* sensor = getFlyskyNv14Sensor(id, subId);
|
||||
telemetrySensor.init(sensor->name, sensor->unit, sensor->precision);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t GetSensorValueFlySkyNv14(const FlyskyNv14Sensor* sensor, const uint8_t * data){
|
||||
int32_t GetSensorValueFlySkyNv14(const FlyskyNv14Sensor* sensor,
|
||||
const uint8_t* data)
|
||||
{
|
||||
int32_t value = 0;
|
||||
const nv14SensorData* sensorData = reinterpret_cast<const nv14SensorData*>(data + sensor->offset);
|
||||
if(sensor->bytes == 1) value = sensorData->UINT8;
|
||||
else if(sensor->bytes == 2) value = sensor->issigned ? sensorData->INT16 : sensorData->UINT16;
|
||||
else if(sensor->bytes == 4) value = sensorData->UINT32;
|
||||
const nv14SensorData* sensorData =
|
||||
reinterpret_cast<const nv14SensorData*>(data + sensor->offset);
|
||||
if (sensor->bytes == 1)
|
||||
value = sensorData->UINT8;
|
||||
else if (sensor->bytes == 2)
|
||||
value = sensor->issigned ? sensorData->INT16 : sensorData->UINT16;
|
||||
else if (sensor->bytes == 4)
|
||||
value = sensorData->UINT32;
|
||||
|
||||
if(sensor->id == FLYSKY_SENSOR_RX_RSSI) {
|
||||
if(value < -200) value = -200;
|
||||
#if defined (PCBNV14)
|
||||
if(!g_model.rssiAlarms.flysky_telemetry)
|
||||
if (sensor->id == FLYSKY_SENSOR_RX_RSSI) {
|
||||
if (value < -200) value = -200;
|
||||
#if defined(PCBNV14)
|
||||
if (!g_model.rssiAlarms.flysky_telemetry)
|
||||
#endif
|
||||
{
|
||||
value += 200;
|
||||
value /= 2;
|
||||
value += 200;
|
||||
value /= 2;
|
||||
}
|
||||
TRACE("RSSI: %d", value);
|
||||
telemetryData.rssi.set(value);
|
||||
}
|
||||
if(sensor->id == FLYSKY_SENSOR_PRESURRE && sensor->subId != 0){
|
||||
if (sensor->id == FLYSKY_SENSOR_PRESSURE && sensor->subId != 0) {
|
||||
value = CalculateAltitude(value, 101325);
|
||||
value = (value+500)/1000;
|
||||
value = (value + 500) / 1000;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void flySkyNv14ProcessTelemetryPacket(const uint8_t * ptr, uint8_t sensorID )
|
||||
void flySkyNv14ProcessTelemetryPacket(uint8_t* ptr, uint8_t len)
|
||||
{
|
||||
uint8_t instnace = *ptr++;
|
||||
if(sensorID == FLYSKY_SENSOR_RX_VOLTAGE) sensorID = FLYSKY_FIXED_RX_VOLTAGE;
|
||||
uint8_t sensorType = *ptr++;
|
||||
uint8_t sensorID = *ptr++;
|
||||
|
||||
TRACE("ID[%02X] Type[%02X] len=%d", ptr[1], ptr[0], len);
|
||||
|
||||
// remove unknown sensor (strange values)
|
||||
if (sensorType == 0xEE) return;
|
||||
if (sensorType == FLYSKY_SENSOR_RX_VOLTAGE)
|
||||
sensorType = FLYSKY_FIXED_RX_VOLTAGE;
|
||||
|
||||
for (const FlyskyNv14Sensor sensor : Nv14Sensor) {
|
||||
if (sensor.id == sensorID) {
|
||||
int32_t value = GetSensorValueFlySkyNv14(&sensor, ptr);
|
||||
setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_NV14, sensor.id, sensor.subId, instnace, value, sensor.unit, sensor.precision);
|
||||
}
|
||||
if (sensor.id == sensorType) {
|
||||
int32_t value = GetSensorValueFlySkyNv14(&sensor, ptr);
|
||||
TRACE("[%02X] id=%02X(%s) subId=%02X value=%d",
|
||||
sensorID, sensor.id, sensor.name, sensor.subId, value);
|
||||
setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_NV14, sensor.id, sensor.subId,
|
||||
sensorID, value, sensor.unit, sensor.precision);
|
||||
}
|
||||
}
|
||||
|
||||
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
|
||||
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,43 +21,7 @@
|
||||
#ifndef __FLYSKY_NV14_H__
|
||||
#define __FLYSKY_NV14_H__
|
||||
|
||||
enum FlySkySensorType_E {
|
||||
FLYSKY_SENSOR_RX_VOLTAGE,
|
||||
FLYSKY_SENSOR_RX_SIGNAL,
|
||||
FLYSKY_SENSOR_RX_RSSI,
|
||||
FLYSKY_SENSOR_RX_NOISE,
|
||||
FLYSKY_SENSOR_RX_SNR,
|
||||
FLYSKY_SENSOR_TEMP,
|
||||
FLYSKY_SENSOR_EXT_VOLTAGE,
|
||||
FLYSKY_SENSOR_MOTO_RPM,
|
||||
FLYSKY_SENSOR_PRESURRE,
|
||||
FLYSKY_SENSOR_GPS
|
||||
};
|
||||
typedef struct FLYSKY_GPS_INFO_S {
|
||||
uint8_t position_fix;
|
||||
uint8_t satell_cnt;
|
||||
uint8_t latitude[4];
|
||||
uint8_t longtitude[4];
|
||||
uint8_t altitude[4];
|
||||
uint8_t g_speed[2];
|
||||
uint8_t direction[2];
|
||||
} gps_info_t;
|
||||
typedef struct FLYSKY_SENSOR_DATA_S {
|
||||
uint8_t sensor_type;
|
||||
uint8_t sensor_id;
|
||||
uint8_t voltage[2];
|
||||
uint8_t signal;
|
||||
uint8_t rssi[2];
|
||||
uint8_t noise[2];
|
||||
uint8_t snr[2];
|
||||
uint8_t temp[2];
|
||||
uint8_t ext_voltage[2];
|
||||
uint8_t moto_rpm[2];
|
||||
uint8_t pressure_value[2];
|
||||
gps_info_t gps_info;
|
||||
} rx_sensor_t;
|
||||
|
||||
void flySkyNv14SetDefault(int index, uint8_t id, uint8_t subId, uint8_t instance);
|
||||
void flySkyNv14ProcessTelemetryPacket(const uint8_t * ptr, uint8_t SensorType );
|
||||
void flySkyNv14ProcessTelemetryPacket(uint8_t * ptr, uint8_t len );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "opentx.h"
|
||||
#include "multi.h"
|
||||
#include "pulses/afhds3.h"
|
||||
#include "pulses/flysky.h"
|
||||
#include "mixer_scheduler.h"
|
||||
#include "io/multi_protolist.h"
|
||||
|
||||
@@ -145,6 +146,18 @@ void telemetryWakeup()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PCBNV14)
|
||||
if (//!moduleUpdateActive(INTERNAL_MODULE) &&
|
||||
moduleState[INTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_AFHDS2A &&
|
||||
intmoduleFifo.pop(data)) {
|
||||
LOG_TELEMETRY_WRITE_START();
|
||||
do {
|
||||
processInternalFlySkyTelemetryData(data);
|
||||
LOG_TELEMETRY_WRITE_BYTE(data);
|
||||
} while (intmoduleFifo.pop(data));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(STM32)
|
||||
if (telemetryGetByte(&data)) {
|
||||
LOG_TELEMETRY_WRITE_START();
|
||||
@@ -432,6 +445,11 @@ void ModuleSyncStatus::update(uint16_t newRefreshRate, int16_t newInputLag)
|
||||
TRACE("[SYNC] update rate = %dus; lag = %dus",refreshRate,currentLag);
|
||||
}
|
||||
|
||||
void ModuleSyncStatus::invalidate() {
|
||||
//make invalid after use
|
||||
currentLag = 0;
|
||||
}
|
||||
|
||||
uint16_t ModuleSyncStatus::getAdjustedRefreshRate()
|
||||
{
|
||||
int16_t lag = currentLag;
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "flysky_ibus.h"
|
||||
#endif
|
||||
|
||||
#include "pulses/modules_helpers.h"
|
||||
|
||||
extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time
|
||||
|
||||
inline bool TELEMETRY_STREAMING()
|
||||
@@ -115,79 +117,62 @@ void frskyDSetDefault(int index, uint16_t id);
|
||||
|
||||
extern uint8_t telemetryProtocol;
|
||||
|
||||
#if defined (MULTIMODULE)
|
||||
#define IS_D16_MULTI(module) (((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) && (g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16 || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_CLONED)) \
|
||||
|| (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX2))
|
||||
#define IS_R9_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY_R9)
|
||||
#define IS_HOTT_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT)
|
||||
#define IS_CONFIG_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_CONFIG)
|
||||
#define IS_DSM_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2)
|
||||
#define IS_RX_MULTI(module) ((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_AFHDS2A_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX_RX) \
|
||||
|| (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_BAYANG_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM_RX))
|
||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||
#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(INTERNAL_MODULE) || IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(INTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE))))
|
||||
#else
|
||||
#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(EXTERNAL_MODULE) || IS_R9_MULTI(EXTERNAL_MODULE))))
|
||||
#endif
|
||||
#else
|
||||
#define IS_D16_MULTI(module) false
|
||||
#define IS_R9_MULTI(module) false
|
||||
#define IS_HOTT_MULTI(module) false
|
||||
#define IS_CONFIG_MULTI(module) false
|
||||
#define IS_DSM_MULTI(module) false
|
||||
#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
|
||||
#define IS_RX_MULTI(module) false
|
||||
#endif
|
||||
|
||||
#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM)
|
||||
|
||||
#if defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
inline bool isSportLineUsedByInternalModule()
|
||||
inline const char* getRssiLabel()
|
||||
{
|
||||
return g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT_PXX1;
|
||||
}
|
||||
#else
|
||||
inline bool isSportLineUsedByInternalModule()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#if defined(MULTIMODULE)
|
||||
if (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE &&
|
||||
(g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() ==
|
||||
MODULE_SUBTYPE_MULTI_FS_AFHDS2A ||
|
||||
g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol() ==
|
||||
MODULE_SUBTYPE_MULTI_HOTT)) {
|
||||
return "RQly";
|
||||
}
|
||||
#endif
|
||||
#if defined(GHOST)
|
||||
if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) {
|
||||
return "RQly";
|
||||
}
|
||||
#endif
|
||||
return "RSSI";
|
||||
}
|
||||
|
||||
inline uint8_t modelTelemetryProtocol()
|
||||
{
|
||||
bool sportUsed = isSportLineUsedByInternalModule();
|
||||
|
||||
#if defined(CROSSFIRE)
|
||||
if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) {
|
||||
if (isModuleCrossfire(EXTERNAL_MODULE)) {
|
||||
return PROTOCOL_TELEMETRY_CROSSFIRE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GHOST)
|
||||
if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST) {
|
||||
if (isModuleGhost(EXTERNAL_MODULE)) {
|
||||
return PROTOCOL_TELEMETRY_GHOST;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) {
|
||||
if (!sportUsed && isModulePPM(EXTERNAL_MODULE)) {
|
||||
return g_model.telemetryProtocol;
|
||||
}
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) {
|
||||
if (!sportUsed && isModuleMultimodule(EXTERNAL_MODULE)) {
|
||||
return PROTOCOL_TELEMETRY_MULTIMODULE;
|
||||
}
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
if (g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE) {
|
||||
if (isModuleMultimodule(INTERNAL_MODULE) && isModuleNone(EXTERNAL_MODULE)) {
|
||||
return PROTOCOL_TELEMETRY_MULTIMODULE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS3)
|
||||
if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_AFHDS3) {
|
||||
if (isModuleAFHDS3(EXTERNAL_MODULE)) {
|
||||
return PROTOCOL_TELEMETRY_AFHDS3;
|
||||
}
|
||||
#endif
|
||||
|
||||
// default choice
|
||||
return PROTOCOL_TELEMETRY_FRSKY_SPORT;
|
||||
}
|
||||
@@ -312,6 +297,9 @@ struct ModuleSyncStatus
|
||||
// Set feedback from RF module
|
||||
void update(uint16_t newRefreshRate, int16_t newInputLag);
|
||||
|
||||
//mark as timeouted
|
||||
void invalidate();
|
||||
|
||||
// Get computed settings for scheduler
|
||||
uint16_t getAdjustedRefreshRate();
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "libopenui.h"
|
||||
#endif
|
||||
|
||||
#include "telemetry/flysky_nv14.h"
|
||||
|
||||
TelemetryItem telemetryItems[MAX_TELEMETRY_SENSORS];
|
||||
uint8_t allowNewSensors;
|
||||
|
||||
@@ -557,6 +559,12 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_TELEMETRY_FLYSKY_NV14:
|
||||
flySkyNv14SetDefault(index, id, subId, instance);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
case PROTOCOL_TELEMETRY_SPEKTRUM:
|
||||
spektrumSetDefault(index, id, subId, instance);
|
||||
|
||||
@@ -75,6 +75,8 @@ ISTR(R9M_PXX2_RF_PROTOCOLS);
|
||||
ISTR(DSM_PROTOCOLS);
|
||||
ISTR(AFHDS3_PROTOCOLS);
|
||||
ISTR(AFHDS3_POWERS);
|
||||
ISTR(FLYSKY_PULSE_PROTO);
|
||||
ISTR(FLYSKY_SERIAL_PROTO);
|
||||
ISTR(CURVE_TYPES);
|
||||
ISTR(VSENSORTYPES);
|
||||
ISTR(VFORMULAS);
|
||||
|
||||
@@ -187,6 +187,9 @@ extern const char STR_AFHDS3_RX_FREQ[];
|
||||
extern const char STR_AFHDS3_ACTUAL_POWER[];
|
||||
extern const char STR_AFHDS3_POWER_SOURCE[];
|
||||
|
||||
extern const char STR_FLYSKY_PULSE_PROTO[];
|
||||
extern const char STR_FLYSKY_SERIAL_PROTO[];
|
||||
|
||||
extern const char STR_CURVE_TYPES[];
|
||||
extern const char STR_VSENSORTYPES[];
|
||||
extern const char STR_VFORMULAS[];
|
||||
|
||||
@@ -176,6 +176,12 @@
|
||||
#define LEN_AFHDS3_POWERS "\006"
|
||||
#define TR_AFHDS3_POWERS "25 mW\0""100 mW""500 mW""1 W\0 ""2 W\0 "
|
||||
|
||||
#define LEN_FLYSKY_PULSE_PROTO "\x003"
|
||||
#define TR_FLYSKY_PULSE_PROTO "PWM""PPM"
|
||||
|
||||
#define LEN_FLYSKY_SERIAL_PROTO "\x004"
|
||||
#define TR_FLYSKY_SERIAL_PROTO "iBUS""SBUS"
|
||||
|
||||
#define LEN_PPM_POL "\001"
|
||||
#define TR_PPM_POL "-""+"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user