feat: Add support for latest FrSky receivers (#4077)

Co-authored-by: Bertrand Songis <bsongis@gmail.com>
Co-authored-by: raphaelcoeffic <raphael.coeffic@frafos.com>
This commit is contained in:
3djc
2023-10-09 19:22:57 +10:00
committed by GitHub
co-authored by Bertrand Songis raphaelcoeffic
parent d684930cc9
commit 5fd22612aa
12 changed files with 410 additions and 151 deletions
+112 -53
View File
@@ -707,27 +707,105 @@ void RxOptions::checkEvents()
Dialog::checkEvents();
}
#define CH_ENABLE_SPORT 4
#define CH_ENABLE_SBUS 5
static uint8_t getShiftedChannel(int8_t moduleIdx, int ch)
{
return g_model.moduleData[moduleIdx].channelsStart + ch;
}
static std::string getChannelText(int8_t moduleIdx, uint8_t pin, int val)
class OutputMappingChoice : public Choice
{
uint8_t ch = getShiftedChannel(moduleIdx, val);
uint8_t channelsMax = sentModuleChannels(moduleIdx) - 1;
if (val <= channelsMax) {
return std::string("CH") + std::to_string(ch + 1);
} else if (pin == CH_ENABLE_SPORT) {
return std::string("S.PORT");
} else if (pin == CH_ENABLE_SBUS) {
return std::string("SBUS");
protected:
uint32_t capabilities;
uint8_t ch_offset;
uint8_t channels;
uint8_t rx_pin;
int getOutputMapping()
{
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
return hwSettings.receiverSettings.outputsMapping[rx_pin];
}
return std::string();
}
void setOutputMapping(int val)
{
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
hwSettings.receiverSettings.outputsMapping[rx_pin] = val;
}
std::string getChannelText(int val)
{
if (val < channels) {
return std::string("CH") + std::to_string(ch_offset + val + 1);
}
return std::string();
}
void addMenuItem(int item, Menu* menu, int val, int& selectedIx)
{
menu->addLineBuffered(textHandler(item), [=]() { setValue(item); });
if (item == val) { selectedIx = menu->count() - 1; }
}
public:
OutputMappingChoice(Window* parent, uint32_t capabilities, uint8_t rx_model_id,
uint8_t module, uint8_t channels, uint8_t output_pin) :
Choice(parent, rect_t{}, 0, channels - 1,
std::bind(&OutputMappingChoice::getOutputMapping, this),
std::bind(&OutputMappingChoice::setOutputMapping, this,
std::placeholders::_1), 0),
capabilities(capabilities),
ch_offset(getShiftedChannel(module, 0)),
channels(channels),
rx_pin(output_pin)
{
if (isPXX2ReceiverOptionAvailable(rx_model_id, RECEIVER_OPTION_D_TELE_PORT)) {
setTextHandler([=] (int val) {
switch(val) {
case CH_MAP_SBUS_IN:
return std::string(STR_SBUSIN);
case CH_MAP_SBUS_OUT:
return std::string(STR_SBUSOUT);
case CH_MAP_SPORT:
return std::string(STR_SPORT);
case CH_MAP_FBUS:
return std::string(STR_FBUS);
default:
return getChannelText(val);
}
});
setFillMenuHandler([=](Menu* menu, int val, int& selectedIx) {
if (output_pin == 0) {
addMenuItem(CH_MAP_SBUS_IN, menu, val, selectedIx);
}
addMenuItem(CH_MAP_SBUS_OUT, menu, val, selectedIx);
addMenuItem(CH_MAP_SPORT, menu, val, selectedIx);
addMenuItem(CH_MAP_FBUS, menu, val, selectedIx);
});
return;
}
if (capabilities & (1 << RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6)) {
if (CH_ENABLE_SPORT == output_pin) {
setTextHandler([=] (int val) {
if (val == channels) return std::string(STR_SPORT);
return getChannelText(val);
});
setMax(channels);
return;
} else if (CH_ENABLE_SBUS == output_pin) {
setTextHandler([=] (int val) {
if (val == channels) return std::string(STR_SBUSOUT);
return getChannelText(val);
});
setMax(channels);
return;
}
}
setTextHandler(std::bind(&OutputMappingChoice::getChannelText, this,
std::placeholders::_1));
}
};
void RxOptions::update()
{
@@ -736,8 +814,8 @@ void RxOptions::update()
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
auto& rxInfo = hwSettings.modules[moduleIdx].receivers[receiverIdx].information;
// uint8_t receiverModelId = rxInfo.modelID;
uint8_t receiverVariant = rxInfo.variant;
uint8_t rxModelId = rxInfo.modelID;
uint8_t rxVariant = rxInfo.variant;
uint8_t capabilities = rxInfo.capabilities;
FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
@@ -775,7 +853,7 @@ void RxOptions::update()
hwSettings.receiverSettings.telemetryDisabled = val;
});
if (isModuleR9MAccess(moduleIdx) && receiverVariant == PXX2_VARIANT_EU &&
if (isModuleR9MAccess(moduleIdx) && rxVariant == PXX2_VARIANT_EU &&
hwSettings.moduleSettings.txPower > 14 /*25mW*/) {
// read only field in this case
tele25mw->disable();
@@ -828,48 +906,29 @@ void RxOptions::update()
});
}
if (capabilities & (1 << RECEIVER_CAPABILITY_SBUS24)) {
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_SBUS24);
new ToggleSwitch(
line, rect_t{},
[]() {
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
return hwSettings.receiverSettings.sbus24;
},
[](int val) {
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
hwSettings.receiverSettings.sbus24 = val;
});
}
auto outputsCount = min<uint8_t>(16, hwSettings.receiverSettings.outputsCount);
for (uint8_t i = 0; i < outputsCount; i++) {
line = form->newLine(&grid);
std::string i_str = std::to_string(i+1);
new StaticText(line, rect_t{}, std::string(STR_PIN) + i_str);
uint8_t channelsMax = sentModuleChannels(moduleIdx) - 1;
uint8_t selectionMax = channelsMax;
if (capabilities & (1 << RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6)
&& (CH_ENABLE_SPORT == i || CH_ENABLE_SBUS == i)) {
selectionMax++;
}
//uint8_t mapping = hwSettings.receiverSettings.outputsMapping[i];
// uint8_t channel = getShiftedChannel(moduleIdx, mapping);
// TODO
// auto r = grid.getFieldSlot(2, 1);
// if (r.h > BAR_HEIGHT) {
// r.y += (r.h - BAR_HEIGHT)/2;
// r.h = BAR_HEIGHT;
// }
// auto chBar = new OutputChannelBar(form, r, channel);
auto chDn = new Choice(
line, rect_t{}, 0, selectionMax,
[=]() {
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
return hwSettings.receiverSettings.outputsMapping[i];
},
[=](int val) {
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
hwSettings.receiverSettings.outputsMapping[i] = val;
// if (val <= channelsMax) {
// chBar->setChannel(getShiftedChannel(moduleIdx, val));
// lv_obj_clear_flag(chBar->getLvObj(), LV_OBJ_FLAG_HIDDEN);
// } else {
// lv_obj_add_flag(chBar->getLvObj(), LV_OBJ_FLAG_HIDDEN);
// }
});
chDn->setTextHandler(
[=](int val) { return getChannelText(moduleIdx, i, val); });
uint8_t channels = sentModuleChannels(moduleIdx);
new OutputMappingChoice(line, capabilities, rxModelId, moduleIdx, channels, i);
}
line = form->newLine(&grid);
+1 -1
View File
@@ -199,7 +199,7 @@ class FrskyOtaFlashDialog : public Dialog
if (reusableBuffer.sdManager.otaUpdateInformation.step == BIND_INFO_REQUEST) {
uint8_t modelId = reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.modelID;
if (isPXX2ReceiverOptionAvailable(modelId, RECEIVER_OPTION_OTA)) {
if (isPXX2ReceiverOptionAvailable(modelId, RECEIVER_OPTION_OTA_TO_UPDATE_SELF)) {
char *tmp = strAppend(reusableBuffer.sdManager.otaReceiverVersion, TR_CURRENT_VERSION);
tmp = strAppendUnsigned(tmp, 1 + reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.major);
*tmp++ = '.';
@@ -49,6 +49,7 @@ enum {
ITEM_RECEIVER_SETTINGS_TELEMETRY,
ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW,
ITEM_RECEIVER_SETTINGS_SPORT_MODE,
ITEM_RECEIVER_SETTINGS_SBUS24,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1,
ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2,
ITEM_RECEIVER_SETTINGS_PINMAP_FIRST
@@ -57,9 +58,6 @@ enum {
#define IS_RECEIVER_CAPABILITY_ENABLED(capability) (reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilities & (1 << capability))
#define IF_RECEIVER_CAPABILITY(capability, count) uint8_t(IS_RECEIVER_CAPABILITY_ENABLED(capability) ? count : HIDDEN_ROW)
#define CH_ENABLE_SPORT 4
#define CH_ENABLE_SBUS 5
bool isSPortModeAvailable(int mode)
{
uint8_t receiverId = reusableBuffer.hardwareAndSettings.receiverSettings.receiverId;
@@ -78,8 +76,17 @@ void menuModelReceiverOptions(event_t event)
if (event == EVT_ENTRY) {
// reusableBuffer.hardwareSettings should have been cleared before calling this menu
#if defined(SIMU)
reusableBuffer.hardwareAndSettings.receiverSettings.state = PXX2_SETTINGS_OK;
reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount = 8;
auto& hwSettings = getPXX2HardwareAndSettingsBuffer();
memclear(&hwSettings, sizeof(hwSettings));
hwSettings.moduleSettings.state = PXX2_SETTINGS_OK;
hwSettings.receiverSettings.state = PXX2_SETTINGS_OK;
moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL;
auto& rxInfo = hwSettings.modules[0].receivers[0].information;
rxInfo.capabilities = 0x62;
hwSettings.receiverSettings.outputsCount = 6;
for (int i=0; i<6; i++) {
hwSettings.receiverSettings.outputsMapping[i] = i;
}
#endif
}
@@ -88,13 +95,14 @@ void menuModelReceiverOptions(event_t event)
uint8_t receiverVariant = reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.variant;
SUBMENU_NOTITLE(ITEM_RECEIVER_SETTINGS_PINMAP_FIRST + outputsCount, {
0, // PWM rate
isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // Telemetry
IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0),
uint8_t((IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT) || IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT2)) ? 0 : HIDDEN_ROW),
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW),
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW),
0 // channels ...
0, // ITEM_RECEIVER_SETTINGS_PWM_RATE
isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // ITEM_RECEIVER_SETTINGS_TELEMETRY
IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0), // ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW
uint8_t((IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT) || IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT2)) ? 0 : HIDDEN_ROW), // ITEM_RECEIVER_SETTINGS_SPORT_MODE
uint8_t(IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_SBUS24) ? 0 : HIDDEN_ROW), // ITEM_RECEIVER_SETTINGS_SBUS24
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), // ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1
uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), // ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2
0 // ITEM_RECEIVER_SETTINGS_PINMAP_FIRST ...
});
if (menuEvent) {
@@ -188,6 +196,13 @@ void menuModelReceiverOptions(event_t event)
break;
}
case ITEM_RECEIVER_SETTINGS_SBUS24:
reusableBuffer.hardwareAndSettings.receiverSettings.sbus24 = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.sbus24, RECEIVER_OPTIONS_2ND_COLUMN, y, STR_SBUS24, attr, event);
if (attr && checkIncDec_Ret) {
reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
}
break;
case ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1:
lcdDrawText(LCD_W/2, y+1, STR_MORE_OPTIONS_AVAILABLE, SMLSIZE|CENTERED);
break;
@@ -201,42 +216,74 @@ void menuModelReceiverOptions(event_t event)
{
uint8_t pin = i - ITEM_RECEIVER_SETTINGS_PINMAP_FIRST;
if (pin < reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount) {
uint8_t & mapping = reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin];
uint8_t channel = g_model.moduleData[g_moduleIdx].channelsStart + mapping;
uint8_t mapping = reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin];
lcdDrawText(0, y, STR_PIN);
lcdDrawNumber(lcdLastRightPos + 1, y, pin + 1);
uint8_t channelMax = sentModuleChannels(g_moduleIdx) - 1;
uint8_t selectionMax = channelMax;
if (IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6)) {
if (CH_ENABLE_SPORT == pin || CH_ENABLE_SBUS == pin)
selectionMax += 1;
if (mapping <= channelMax) {
uint8_t channel = g_model.moduleData[g_moduleIdx].channelsStart + mapping;
putsChn(7 * FW, y, channel + 1, attr);
}
if (CH_ENABLE_SPORT == pin && selectionMax == channel) {
lcdDrawText(7 * FW, y, "S.PORT", attr);
if (isPXX2ReceiverOptionAvailable(receiverModelId, RECEIVER_OPTION_D_TELE_PORT)) {
if (mapping == CH_MAP_SPORT) {
lcdDrawText(7 * FW, y, STR_SPORT, attr);
mapping = channelMax + 1;
} else if (mapping == CH_MAP_SBUS_OUT) {
lcdDrawText(7 * FW, y, STR_SBUSOUT, attr);
mapping = channelMax + 2;
} else if (mapping == CH_MAP_FBUS) {
lcdDrawText(7 * FW, y, STR_FBUS, attr);
mapping = channelMax + 3;
}
else if (CH_ENABLE_SBUS == pin && selectionMax == channel) {
lcdDrawText(7 * FW, y, "SBUS", attr);
if (pin == 0) {
selectionMax = channelMax + 4;
if (mapping == CH_MAP_SBUS_IN) {
lcdDrawText(7 * FW, y, STR_SBUSIN, attr);
mapping = selectionMax;
}
}
else {
putsChn(7 * FW, y, channel + 1, attr);
selectionMax = channelMax + 3;
}
} else if (IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6)) {
if (CH_ENABLE_SPORT == pin) {
if (++selectionMax == mapping) {
lcdDrawText(7 * FW, y, STR_SPORT, attr);
}
} else if (CH_ENABLE_SBUS == pin) {
if (++selectionMax == mapping) {
lcdDrawText(7 * FW, y, STR_SBUSOUT, attr);
}
}
}
else {
putsChn(7 * FW, y, channel + 1, attr);
}
// Channel
if (attr) {
mapping = checkIncDec(event, mapping, 0, selectionMax);
if (checkIncDec_Ret) {
if (isPXX2ReceiverOptionAvailable(receiverModelId, RECEIVER_OPTION_D_TELE_PORT)) {
if (mapping == channelMax + 1) {
mapping = CH_MAP_SPORT;
} else if (mapping == channelMax + 2) {
mapping = CH_MAP_SBUS_OUT;
} else if (mapping == channelMax + 3) {
mapping = CH_MAP_FBUS;
} else if (mapping == channelMax + 4) {
mapping = CH_MAP_SBUS_IN;
}
}
reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin] = mapping;
reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY;
}
}
// Bargraph
if (channel <= channelMax) {
if (mapping <= channelMax) {
uint8_t channel = g_model.moduleData[g_moduleIdx].channelsStart + mapping;
int32_t channelValue = channelOutputs[channel];
#if !(defined(PCBX7) || defined(PCBX9LITE) || defined(PCBX9LITES)) // X7/X9 LCD doesn't like too many horizontal lines
lcdDrawRect(RECEIVER_OPTIONS_2ND_COLUMN, y + 2, wbar + 1, 4);
@@ -88,7 +88,7 @@ void onUpdateStateChanged()
{
if (reusableBuffer.sdManager.otaUpdateInformation.step == BIND_INFO_REQUEST) {
uint8_t modelId = reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.modelID;
if (isPXX2ReceiverOptionAvailable(modelId, RECEIVER_OPTION_OTA)) {
if (isPXX2ReceiverOptionAvailable(modelId, RECEIVER_OPTION_OTA_TO_UPDATE_SELF)) {
POPUP_CONFIRMATION(getPXX2ReceiverName(modelId), onUpdateConfirmation);
char *tmp = strAppend(reusableBuffer.sdManager.otaReceiverVersion, TR_CURRENT_VERSION);
tmp = strAppendUnsigned(tmp, 1 + reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.major);
+92 -34
View File
@@ -80,44 +80,100 @@ bool isPXX2ModuleOptionAvailable(uint8_t modelId, uint8_t option)
}
/* Receiver options order:
* - OTA (0x01)
* - 2.4G (0x01)
* - 900M (0x02)
* - OTA to update self (0x04)
* - OTA to update sensors (0x08)
* - Tandem Receiver (0x10)
* - Twin Receiver (0x20)
* - Dynamic Telemetry Port (0x40)
*/
static const uint8_t PXX2ReceiverOptions[] = {
#if defined(SIMU)
0b11111111, // None = display all options on SIMU
0b11111111, // None = display all options on SIMU
#else
0b00000000, // None = display all options on SIMU
0b00000000, // None
#endif
0b11111110, // X8R
0b11111110, // RX8R
0b11111110, // RX8R-PRO
0b11111111, // RX6R
0b11111111, // RX4R
0b11111111, // G-RX8
0b11111111, // G-RX6
0b11111110, // X6R
0b11111110, // X4R
0b11111110, // X4R-SB
0b11111110, // XSR
0b11111110, // XSR-M
0b11111111, // RXSR
0b11111110, // S6R
0b11111110, // S8R
0b11111110, // XM
0b11111110, // XM+
0b11111110, // XMR
0b11111110, // R9
0b11111110, // R9-SLIM
0b11111110, // R9-SLIM+
0b11111110, // R9-MINI
0b11111110, // R9-MM
0b11111111, // R9-STAB+OTA
0b11111111, // R9-MINI+OTA
0b11111111, // R9-MM+OTA
0b11111111, // R9-SLIM+OTA
0b11111111, // ARCHER-X
0b11111111, // R9MX
0b11111111, // R9SX
0b00000001, // X8R
0b00000001, // RX8R
0b00000001, // RX8R-PRO
0b00001001, // RX6R, flash sensors by OTA
0b00001001, // RX4R, flash sensors by OTA
0b00001001, // G-RX8, flash sensors by OTA
0b00001001, // G-RX6, flash sensors by OTA
0b00000001, // X6R
0b00000001, // X4R
0b00000001, // X4R-SB
0b00000001, // XSR
0b00000001, // XSR-M
0b00001001, // RXSR, flash sensors by OTA
0b00000001, // S6R
0b00000001, // S8R
0b00000001, // XM
0b00000001, // XM+
0b00000001, // XMR
0b00000010, // R9
0b00000010, // R9-SLIM
0b00000010, // R9-SLIM+
0b00000010, // R9-MINI
0b00000010, // R9-MM
0b00001110, // R9-STAB+OTA, flash self + sensors by OTA
0b00001110, // R9-MINI+OTA, flash self + sensors by OTA
0b00001110, // R9-MM+OTA, flash self + sensors by OTA
0b00001110, // R9-SLIM+OTA, flash self + sensors by OTA
0b00001101, // ARCHER-X, flash self + sensors by OTA
0b00001110, // R9MX, flash self + sensors by OTA
0b00001110, // R9SX, flash self + sensors by OTA
0b00010100, // TDMX, flash self by OTA
0b01010100, // TDR18, flash self by OTA
0b01010100, // TDR10, flash self by OTA
0b00010100, // TDR6, flash self by OTA
0b01010100, // TDR12
0b01010100, // TDSR12
0b01010100, // TDSR18
0b00010100, // 0x26
0b00010100,
0b00010100,
0b00010100,
0b00010100, // 0x2A
0b00010100,
0b00010100,
0b00010100,
0b00010100,
0b00010100, // 0x2F
0b00010100, // reserve 0x23 ~ 0x30 for TD Receivers
0b00100100, // TWMX, flash self by OTA
0b01100100, // TWSR12, flash self by OTA
0b01100100, // TWR12, flash self by OTA
0b00100100, // TWGR6, flash self by OTA
0b00100100, // TWGR8
0b00100100, // TWR6
0b00100100, // TWR8
0b00100100, // TWGR6FB
0b00100100, // TWR6FB
0b00100100, // 0x3A
0b00100100,
0b00100100,
0b00100100,
0b00100100,
0b00100100, // reserve 0x38 ~ 0x3F for TW Receivers
0b01001101, // SR10-plus
0b01001101, // R10-plus
0b00001101, // GR8-plus
0b00001101, // R8-plus
0b00001101, // SR8-plus
0b00001101, // GR6-plus
0b00001101, // R6-plus
0b00001101, // R6M (ESC DC)
0b00001101, // RS-plus
0b00001101, // RS Mini
0b00001101, // R6FB
0b00001101, // GR6FB
0b01001101, // SR12-plus
0b01001101, // R12-plus
0b00001101, // R6 Mini E
0b00001101, // SR6 Mini
0b00001101, // SR6 Mini E
};
uint8_t getPXX2ReceiverOptions(uint8_t modelId)
@@ -413,10 +469,12 @@ void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module, int16_t* channels, u
flag1 |= PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6;
if (reusableBuffer.hardwareAndSettings.receiverSettings.fport2)
flag1 |= PXX2_RX_SETTINGS_FLAG1_FPORT2;
if (reusableBuffer.hardwareAndSettings.receiverSettings.sbus24)
flag1 |= PXX2_RX_SETTINGS_FLAG1_SBUS24;
Pxx2Transport::addByte(flag1);
uint8_t outputsCount = min<uint8_t>(24, reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount);
for (int i = 0; i < outputsCount; i++) {
Pxx2Transport::addByte(min<uint8_t>(23, reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[i]));
Pxx2Transport::addByte(reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[i]);
}
}
reusableBuffer.hardwareAndSettings.receiverSettings.timeout = get_tmr10ms() + 200/*next try in 2s*/;
+20 -1
View File
@@ -55,6 +55,7 @@
#define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED (1 << 7)
#define PXX2_RX_SETTINGS_FLAG1_READONLY (1 << 6)
#define PXX2_RX_SETTINGS_FLAG1_SBUS24 (1 << 5)
#define PXX2_RX_SETTINGS_FLAG1_FASTPWM (1 << 4)
#define PXX2_RX_SETTINGS_FLAG1_FPORT (1 << 3)
#define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW (1 << 2)
@@ -70,6 +71,16 @@
#define PXX2_AUTH_REFUSED_FLAG 0xA5
// Channel mapping constants
#define CH_ENABLE_SPORT 4
#define CH_ENABLE_SBUS 5
#define CH_MAP_SPORT 0x40
#define CH_MAP_SBUS_OUT 0x80
#define CH_MAP_SBUS_IN 0xA0
#define CH_MAP_FBUS 0xC0
enum PXX2ModuleModelID {
PXX2_MODULE_NONE,
PXX2_MODULE_XJT,
@@ -106,7 +117,13 @@ enum ModuleCapabilities {
const char * getPXX2ReceiverName(uint8_t modelId);
enum {
RECEIVER_OPTION_OTA,
RECEIVER_OPTION_24G,
RECEIVER_OPTION_900M,
RECEIVER_OPTION_OTA_TO_UPDATE_SELF,
RECEIVER_OPTION_OTA_TO_UPDATE_OTHER,
RECEIVER_OPTION_TANDEM,
RECEIVER_OPTION_TWIN,
RECEIVER_OPTION_D_TELE_PORT,
};
uint8_t getPXX2ReceiverOptions(uint8_t modelId);
@@ -118,6 +135,7 @@ enum ReceiverCapabilities {
RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6,
RECEIVER_CAPABILITY_FPORT2,
RECEIVER_CAPABILITY_RACING_MODE,
RECEIVER_CAPABILITY_SBUS24,
RECEIVER_CAPABILITY_COUNT
};
@@ -230,6 +248,7 @@ class ReceiverSettings {
uint8_t fport;
uint8_t enablePwmCh5Ch6;
uint8_t fport2;
uint8_t sbus24;
uint8_t outputsCount;
uint8_t outputsMapping[24];
};
+2
View File
@@ -102,6 +102,8 @@
#define ACCY_LAST_ID 0x071F
#define ACCZ_FIRST_ID 0x0720
#define ACCZ_LAST_ID 0x072F
#define ANGLE_FIRST_ID 0x0730
#define ANGLE_LAST_ID 0x073F
#define GPS_LONG_LATI_FIRST_ID 0x0800
#define GPS_LONG_LATI_LAST_ID 0x080F
#define GPS_ALT_FIRST_ID 0x0820
+87 -34
View File
@@ -39,8 +39,8 @@ static const char * const PXX2ModulesNames[] = {
"ISRM-PRO",
"ISRM-S",
"R9M",
"R9MLite",
"R9MLite-PRO",
"R9M Lite",
"R9M Lite Pro",
"ISRM-N",
"ISRM-S-X9",
"ISRM-S-X10E",
@@ -58,37 +58,87 @@ const char * getPXX2ModuleName(uint8_t modelId)
}
static const char * const PXX2ReceiversNames[] = {
"---",
"X8R",
"RX8R",
"RX8R-PRO",
"RX6R",
"RX4R",
"G-RX8",
"G-RX6",
"X6R",
"X4R",
"X4R-SB",
"XSR",
"XSR-M",
"RXSR",
"S6R",
"S8R",
"XM",
"XM+",
"XMR",
"R9",
"R9-SLIM",
"R9-SLIM+",
"R9-MINI",
"R9-MM",
"R9-STAB", // R9-STAB has OTA
"R9-MINI-OTA", // this one has OTA (different bootloader)
"R9-MM-OTA", // this one has OTA (different bootloader)
"R9-SLIM+-OTA", // this one has OTA (different bootloader)
"Archer-X", // this one has OTA (internal module)
"R9MX", // this one has OTA
"R9SX", // this one has OTA
"---",
"X8R",
"RX8R",
"RX8R Pro",
"RX6R",
"RX4R",
"G-RX8",
"G-RX6",
"X6R",
"X4R",
"X4R SB",
"XSR",
"XSR M",
"RXSR",
"S6R",
"S8R",
"XM",
"XM+",
"XMR",
"R9",
"R9 SLIM",
"R9 SLIM+",
"R9 MINI",
"R9 MM",
"R9 Stab",
"R9 Mini OTA",
"R9 MM OTA",
"R9 SLIM+ OTA",
"Archer X",
"R9MX",
"R9SX",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"SR10 Plus", // 0x40
"R10 Plus",
"GR8 Plus",
"R8 Plus",
"SR8 Plus",
"GR6 Plus",
"R6 Plus",
"R6M (ESC DC)",
"Rs Plus",
"RS Mini",
"R6FB",
"GR6FB",
"SR12 Plus",
"R12 Plus",
"R6 Mini ESC",
"SR6 Mini",
"SR6 Mini ESC", // 0x50
};
const char * getPXX2ReceiverName(uint8_t modelId)
@@ -120,7 +170,7 @@ static void processGetHardwareInfoFrame(uint8_t module, const uint8_t * frame)
POPUP_WARNING(STR_MODULE_UPGRADE_ALERT);
}
}
else if (index < PXX2_MAX_RECEIVERS_PER_MODULE && modelId < DIM(PXX2ReceiversNames)) {
else if (index < PXX2_MAX_RECEIVERS_PER_MODULE) {
memcpy(&destination->receivers[index].information, &frame[4], length);
destination->receivers[index].timestamp = get_tmr10ms();
if (destination->receivers[index].information.capabilities & ~((1 << RECEIVER_CAPABILITY_COUNT) - 1))
@@ -174,6 +224,9 @@ static void processReceiverSettingsFrame(uint8_t module, const uint8_t * frame)
if (frame[4] & PXX2_RX_SETTINGS_FLAG1_FPORT2)
destination->fport2 = 1;
if (frame[4] & PXX2_RX_SETTINGS_FLAG1_SBUS24)
destination->sbus24 = 1;
uint8_t outputsCount = min<uint8_t>(16, frame[0] - 4);
destination->outputsCount = outputsCount;
for (uint8_t pin = 0; pin < outputsCount; pin++) {
+6
View File
@@ -54,6 +54,8 @@ const FrSkySportSensor sportSensors[] = {
FS( ACCX_FIRST_ID, ACCX_LAST_ID, 0, STR_SENSOR_ACCX, UNIT_G, 3 ),
FS( ACCY_FIRST_ID, ACCY_LAST_ID, 0, STR_SENSOR_ACCY, UNIT_G, 3 ),
FS( ACCZ_FIRST_ID, ACCZ_LAST_ID, 0, STR_SENSOR_ACCZ, UNIT_G, 3 ),
FS( ANGLE_FIRST_ID, ANGLE_LAST_ID, 0, STR_SENSOR_ROLL, UNIT_DEGREE, 2 ),
FS( ANGLE_FIRST_ID, ANGLE_LAST_ID, 1, STR_SENSOR_PITCH, UNIT_DEGREE, 2 ),
FS( CURR_FIRST_ID, CURR_LAST_ID, 0, STR_SENSOR_CURR, UNIT_AMPS, 1 ),
FS( VFAS_FIRST_ID, VFAS_LAST_ID, 0, STR_SENSOR_VFAS, UNIT_VOLTS, 2 ),
FS( AIR_SPEED_FIRST_ID, AIR_SPEED_LAST_ID, 0, STR_SENSOR_ASPD, UNIT_KTS, 1 ),
@@ -417,6 +419,10 @@ void sportProcessTelemetryPacketWithoutCrc(uint8_t module, uint8_t origin, const
servosState = newServosState;
}
}
else if (dataId >= ANGLE_FIRST_ID && dataId <= ANGLE_LAST_ID) {
sportProcessTelemetryPacket(dataId, 0, instance, data & 0xFFFFu);
sportProcessTelemetryPacket(dataId, 1, instance, data >> 16u);
}
else {
sportProcessTelemetryPacket(dataId, 0, instance, data);
}
+3
View File
@@ -212,6 +212,9 @@ void Choice::fillMenu(Menu *menu, const FilterFct& filter)
if (i == 0) { selectedIx0 = count; }
++count;
}
if (fillMenuHandler) {
fillMenuHandler(menu, value, selectedIx);
}
menu->updateLines();
// Force update - in case selected row is first row
menu->select(-1);
+6
View File
@@ -90,6 +90,11 @@ class Choice: public ChoiceBase {
void onClicked() override;
void setFillMenuHandler(std::function<void(Menu*, int, int&)> handler)
{
fillMenuHandler = std::move(handler);
}
void setBeforeDisplayMenuHandler(std::function<void(Menu*)> handler)
{
beforeDisplayMenuHandler = std::move(handler);
@@ -187,6 +192,7 @@ class Choice: public ChoiceBase {
std::function<void(int)> _setValue;
std::function<bool(int)> isValueAvailable;
std::function<std::string(int)> textHandler;
std::function<void(Menu *, int, int&)> fillMenuHandler;
std::function <void(Menu *)> beforeDisplayMenuHandler;
typedef std::function<bool(int16_t)> FilterFct;
+7 -1
View File
@@ -72,7 +72,13 @@
#define TR_XJT_ACCST_RF_PROTOCOLS "D16","D8","LR12"
#define TR_ISRM_RF_PROTOCOLS "ACCESS","D16","LR12"
#define TR_SPORT_MODES "S.PORT","F.PORT","FBUS(FPORT2)"
// ACCESS STUFF
#define STR_SBUSIN "SBUS in"
#define STR_SBUSOUT "SBUS out"
#define STR_SPORT "S.PORT"
#define STR_FBUS "FBUS"
#define STR_SBUS24 "SBUS24"
#define TR_SPORT_MODES STR_SPORT,"F.PORT",STR_FBUS
#define TR_R9M_PXX2_RF_PROTOCOLS "ACCESS","FCC","EU","Flex"
#define TR_R9M_REGION "FCC","EU","868MHz","915MHz"
#define TR_R9M_LITE_FCC_POWER_VALUES "(100mW)"