Skip to content

Commit

Permalink
feat: ELRS bind command support (#4907)
Browse files Browse the repository at this point in the history
  • Loading branch information
3djc authored Jun 2, 2024
1 parent c81c8b5 commit d454509
Show file tree
Hide file tree
Showing 30 changed files with 174 additions and 29 deletions.
7 changes: 6 additions & 1 deletion radio/src/gui/128x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1837,7 +1837,10 @@ void menuModelSetup(event_t event)
l_posHorz += 1;
}
if (isModuleBindRangeAvailable(moduleIdx)) {
lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0);
if (TELEMETRY_STREAMING() && isModuleELRS(moduleIdx))
lcdDrawText(bindButtonPos, y, STR_MODULE_UNBIND, l_posHorz == 1 ? attr : 0);
else
lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0);
if (isModuleRangeAvailable(moduleIdx)) {
lcdDrawText(lcdNextPos + 2, y, STR_MODULE_RANGE, l_posHorz == 2 ? attr : 0);
}
Expand Down Expand Up @@ -1881,6 +1884,8 @@ void menuModelSetup(event_t event)
}
else {
newFlag = MODULE_MODE_BIND;
if (isModuleELRS(moduleIdx))
AUDIO_PLAY(AU_SPECIAL_SOUND_CHEEP); // Since ELRS bind is just one frame, we need to play the sound manually
}

if (!event && (oldFlag != newFlag) &&
Expand Down
7 changes: 6 additions & 1 deletion radio/src/gui/212x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1562,7 +1562,10 @@ void menuModelSetup(event_t event)
l_posHorz += 1;
}
if (isModuleBindRangeAvailable(moduleIdx)) {
lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0);
if (TELEMETRY_STREAMING() && isModuleCrossfire(moduleIdx))
lcdDrawText(bindButtonPos, y, STR_MODULE_UNBIND, l_posHorz == 1 ? attr : 0);
else
lcdDrawText(bindButtonPos, y, STR_MODULE_BIND, l_posHorz == 1 ? attr : 0);
if (isModuleRangeAvailable(moduleIdx)) {
lcdDrawText(lcdNextPos + FW, y, STR_MODULE_RANGE, l_posHorz == 2 ? attr : 0);
}
Expand Down Expand Up @@ -1600,6 +1603,8 @@ void menuModelSetup(event_t event)
}
else {
newFlag = MODULE_MODE_BIND;
if (isModuleCrossfire(moduleIdx))
AUDIO_PLAY(AU_SPECIAL_SOUND_CHEEP); // Since ELRS bind is just one frame, we need to play the sound manually
}

if (!event && (oldFlag != newFlag) &&
Expand Down
19 changes: 18 additions & 1 deletion radio/src/gui/colorlcd/module_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ class ModuleWindow : public Window
void startRSSIDialog(std::function<void()> closeHandler = nullptr);

void updateIDStaticText(int mdIdx);

void checkEvents() override;
};

struct FailsafeChoice : public Window {
Expand Down Expand Up @@ -156,6 +158,19 @@ ModuleWindow::ModuleWindow(Window* parent, uint8_t moduleIdx) :
lv_obj_add_event_cb(lvobj, mw_refresh_cb, LV_EVENT_REFRESH, this);
}

void ModuleWindow::checkEvents()
{
if (bindButton != nullptr) {
if (TELEMETRY_STREAMING() && isModuleELRS(moduleIdx))
bindButton->setText(STR_MODULE_UNBIND);
else if (isModuleELRS(moduleIdx))
bindButton->setText(STR_MODULE_BIND);

bindButton->show(isModuleBindRangeAvailable(moduleIdx));
}
Window::checkEvents();
}

void ModuleWindow::updateIDStaticText(int mdIdx)
{
if (idUnique == nullptr) return;
Expand Down Expand Up @@ -280,7 +295,7 @@ void ModuleWindow::updateModule()
}
});

if (isModuleBindRangeAvailable(moduleIdx)) {
if (isModuleBindRangeAvailable(moduleIdx) || isModuleCrossfire(moduleIdx)) {
bindButton = new TextButton(box, rect_t{}, STR_MODULE_BIND);
bindButton->setPressHandler([=]() -> uint8_t {
if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK) {
Expand Down Expand Up @@ -312,6 +327,8 @@ void ModuleWindow::updateModule()
}
#endif
moduleState[moduleIdx].mode = MODULE_MODE_BIND;
if (isModuleELRS(moduleIdx))
AUDIO_PLAY(AU_SPECIAL_SOUND_CHEEP); // Since ELRS bind is just one frame, we need to play the sound manually
#if defined(AFHDS2)
if (isModuleAFHDS2A(moduleIdx)) {
resetPulsesAFHDS2();
Expand Down
4 changes: 3 additions & 1 deletion radio/src/gui/colorlcd/radio_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class VersionDialog : public BaseDialog
new StaticText(int_rx_name_w, rect_t{}, "");
int_rx_name_w->hide();

// internal reciever status
// internal receiver status
int_rx_status_w = form->newLine(grid);
new StaticText(int_rx_status_w, rect_t{}, STR_STATUS);
int_rx_status =
Expand Down Expand Up @@ -195,6 +195,8 @@ class VersionDialog : public BaseDialog
// snprintf(statusText, 64, "%d Hz %" PRIu32 " Err", hz, telemetryErrors);
snprintf(statusText, 64, "%d Hz", hz);
status->setText(statusText);
snprintf(statusText, 64, "%s V%u.%u.%u", crossfireModuleStatus[module].name, crossfireModuleStatus[module].major, crossfireModuleStatus[module].minor, crossfireModuleStatus[module].revision);
name->setText(statusText);
module_status_w->show();
}
#endif
Expand Down
27 changes: 20 additions & 7 deletions radio/src/gui/common/stdlcd/radio_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#define MENU_BODY_TOP (FH + 1)
#define MENU_BODY_BOTTOM (LCD_H)

#if defined(PXX2)
#if defined(PXX2) || defined(CROSSFIRE)
constexpr uint8_t COLUMN2_X = 10 * FW;
#endif

Expand Down Expand Up @@ -84,7 +84,8 @@ void drawPXX2FullVersion(coord_t x, coord_t y, PXX2Version hwVersion, PXX2Versio
lcdDrawText(lcdNextPos, y, "/");
drawPXX2Version(lcdNextPos, y, swVersion);
}

#endif
#if defined(PXX2) || defined(CROSSFIRE)
void menuRadioModulesVersion(event_t event)
{
if (menuEvent) {
Expand All @@ -95,8 +96,8 @@ void menuRadioModulesVersion(event_t event)
}

title(STR_MENU_MODULES_RX_VERSION);

if (event == EVT_ENTRY) {
#if defined(PXX2)
if (event == EVT_ENTRY) {
memclear(&reusableBuffer.hardwareAndSettings.modules, sizeof(reusableBuffer.hardwareAndSettings.modules));
}

Expand All @@ -116,6 +117,7 @@ void menuRadioModulesVersion(event_t event)

reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms() + 1000 /* 10s*/;
}
#endif

coord_t y = (FH + 1) - menuVerticalOffset * FH;

Expand Down Expand Up @@ -166,6 +168,14 @@ void menuRadioModulesVersion(event_t event)
1000000 / getMixerSchedulerPeriod()/*, UINT32_C(telemetryErrors)*/);
lcdDrawText(COLUMN2_X, y, statusText);
y += FH;
lcdDrawText(INDENT_WIDTH, y, crossfireModuleStatus[module].name);
lcdDrawChar(lcdNextPos + 5, y, 'V');
lcdDrawNumber(lcdNextPos, y, crossfireModuleStatus[module].major);
lcdDrawChar(lcdNextPos, y, '.');
lcdDrawNumber(lcdNextPos, y, crossfireModuleStatus[module].minor);
lcdDrawChar(lcdNextPos, y, '.');
lcdDrawNumber(lcdNextPos, y, crossfireModuleStatus[module].revision);
y += FH;
continue;
}
#endif
Expand All @@ -174,12 +184,14 @@ void menuRadioModulesVersion(event_t event)
y += FH;
continue;
}
#if defined(PXX2)
uint8_t modelId = reusableBuffer.hardwareAndSettings.modules[module]
.information.modelID;
lcdDrawText(COLUMN2_X, y, getPXX2ModuleName(modelId));
#endif
}
y += FH;

#if defined(PXX2)
// Module version
if (y >= MENU_BODY_TOP && y < MENU_BODY_BOTTOM) {
if (reusableBuffer.hardwareAndSettings.modules[module].information.modelID) {
Expand Down Expand Up @@ -211,6 +223,7 @@ void menuRadioModulesVersion(event_t event)
y += FH;
}
}
#endif
}

uint8_t lines = (y - (FH + 1)) / FH + menuVerticalOffset;
Expand Down Expand Up @@ -243,7 +256,7 @@ enum MenuRadioVersionItems
#if defined(PCBTARANIS)
ITEM_RADIO_FIRMWARE_OPTIONS,
#endif
#if defined(PXX2)
#if defined(PXX2) || defined(CROSSFIRE)
ITEM_RADIO_MODULES_VERSION,
#endif
ITEM_RADIO_VERSION_COUNT
Expand All @@ -266,7 +279,7 @@ void menuRadioVersion(event_t event)
}
#endif

#if defined(PXX2)
#if defined(PXX2) || defined(CROSSFIRE)
lcdDrawText(INDENT_WIDTH, y, BUTTON(TR_MODULES_RX_VERSION), menuVerticalPosition == ITEM_RADIO_MODULES_VERSION ? INVERS : 0);
y += FH;
if (menuVerticalPosition == ITEM_RADIO_MODULES_VERSION && event == EVT_KEY_BREAK(KEY_ENTER)) {
Expand Down
3 changes: 3 additions & 0 deletions radio/src/gui/gui_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,9 @@ uint8_t MENU_FIRST_LINE_EDIT(const uint8_t * horTab, uint8_t horTabMax)

uint8_t MODULE_BIND_ROWS(int moduleIdx)
{
if (isModuleELRS(moduleIdx) && (crossfireModuleStatus[moduleIdx].major >= 4 || (crossfireModuleStatus[moduleIdx].major == 3 && crossfireModuleStatus[moduleIdx].minor >= 4)))
return 1;

if (isModuleCrossfire(moduleIdx))
return 0;

Expand Down
39 changes: 39 additions & 0 deletions radio/src/pulses/crossfire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,36 @@

#define MIN_FRAME_LEN 3

uint8_t createCrossfireBindFrame(uint8_t moduleIdx, uint8_t * frame)
{
uint8_t * buf = frame;
*buf++ = UART_SYNC; /* device address */
*buf++ = 7; /* frame length */
*buf++ = COMMAND_ID; /* cmd type */
if (TELEMETRY_STREAMING())
*buf++ = RECEIVER_ADDRESS; /* Destination is receiver (unbind) */
else
*buf++ = MODULE_ADDRESS; /* Destination is module */
*buf++ = RADIO_ADDRESS; /* Origin Address */
*buf++ = SUBCOMMAND_CRSF; /* sub command */
*buf++ = SUBCOMMAND_CRSF_BIND; /* initiate bind */
*buf++ = crc8_BA(frame + 2, 5);
*buf++ = crc8(frame + 2, 6);
return buf - frame;
}

uint8_t createCrossfirePingFrame(uint8_t moduleIdx, uint8_t * frame)
{
uint8_t * buf = frame;
*buf++ = UART_SYNC; /* device address */
*buf++ = 4; /* frame length */
*buf++ = PING_DEVICES_ID; /* cmd type */
*buf++ = BROADCAST_ADDRESS; /* Destination Address */
*buf++ = RADIO_ADDRESS; /* Origin Address */
*buf++ = crc8(frame + 2, 3);
return buf - frame;
}

uint8_t createCrossfireModelIDFrame(uint8_t moduleIdx, uint8_t * frame)
{
uint8_t * buf = frame;
Expand Down Expand Up @@ -98,6 +128,11 @@ static void setupPulsesCrossfire(uint8_t module, uint8_t*& p_buf,
if (moduleState[module].counter == CRSF_FRAME_MODELID) {
p_buf += createCrossfireModelIDFrame(module, p_buf);
moduleState[module].counter = CRSF_FRAME_MODELID_SENT;
} else if (moduleState[module].counter == CRSF_FRAME_MODELID_SENT && crossfireModuleStatus[module].queryCompleted == false) {
p_buf += createCrossfirePingFrame(module, p_buf);
} else if (moduleState[module].mode == MODULE_MODE_BIND) {
p_buf += createCrossfireBindFrame(module, p_buf);
moduleState[module].mode = MODULE_MODE_NORMAL;
} else {
/* TODO: nChannels */
p_buf += createCrossfireChannelsFrame(p_buf, channels);
Expand Down Expand Up @@ -307,6 +342,8 @@ static void* crossfireInit(uint8_t module)
}
#endif
}

memset(&crossfireModuleStatus[module], 0, sizeof(crossfireModuleStatus[module]));
}
#endif

Expand All @@ -321,6 +358,8 @@ static void crossfireDeInit(void* ctx)
{
auto mod_st = (etx_module_state_t*)ctx;

memset(&crossfireModuleStatus[modulePortGetModule(mod_st)], 0, sizeof(crossfireModuleStatus[modulePortGetModule(mod_st)]));

#if !defined(SIMU)
if (mod_st && (modulePortGetModule(mod_st) == EXTERNAL_MODULE)) {
auto drv = modulePortGetSerialDrv(mod_st->rx);
Expand Down
16 changes: 14 additions & 2 deletions radio/src/pulses/modules_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "globals.h"
#include "MultiProtoDefs.h"
#include "hal/module_port.h"
#include "telemetry/crossfire.h"

#if defined(MULTIMODULE)
#include "telemetry/multi.h"
Expand Down Expand Up @@ -227,6 +228,11 @@ inline bool isModuleCrossfire(uint8_t idx)
return g_model.moduleData[idx].type == MODULE_TYPE_CROSSFIRE;
}

inline bool isModuleELRS(uint8_t idx)
{
return crossfireModuleStatus[idx].isELRS;
}

inline bool isInternalModuleCrossfire()
{
return g_eeGeneral.internalModule == MODULE_TYPE_CROSSFIRE;
Expand All @@ -237,6 +243,11 @@ inline bool isModuleCrossfire(uint8_t idx)
return false;
}

inline bool isModuleELRS(uint8_t idx)
{
return false;
}

inline bool isInternalModuleCrossfire()
{
return false;
Expand Down Expand Up @@ -607,7 +618,8 @@ inline bool isModuleBindRangeAvailable(uint8_t moduleIdx)
{
return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) ||
isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx) ||
isModuleFlySky(moduleIdx) || isModuleDSMP(moduleIdx);
isModuleFlySky(moduleIdx) || isModuleDSMP(moduleIdx) ||
(isModuleELRS(moduleIdx) && (crossfireModuleStatus[moduleIdx].major >= 4 || (crossfireModuleStatus[moduleIdx].major == 3 && crossfireModuleStatus[moduleIdx].minor >= 4)));
}

inline uint32_t getNV14RfFwVersion()
Expand All @@ -621,7 +633,7 @@ inline uint32_t getNV14RfFwVersion()

inline bool isModuleRangeAvailable(uint8_t moduleIdx)
{
bool ret = isModuleBindRangeAvailable(moduleIdx) && !IS_RX_MULTI(moduleIdx);
bool ret = isModuleBindRangeAvailable(moduleIdx) && !IS_RX_MULTI(moduleIdx) && !isModuleCrossfire(moduleIdx);
#if defined(PCBNV14) && defined(AFHDS2)
ret = ret &&
(!isModuleAFHDS2A(moduleIdx) || NV14internalModuleFwVersion >= 0x1000E);
Expand Down
15 changes: 14 additions & 1 deletion radio/src/telemetry/crossfire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
*/

#include "crossfire.h"

#include "opentx.h"

// clang-format off
Expand Down Expand Up @@ -62,6 +61,8 @@ const CrossfireSensor crossfireSensors[] = {
};
// clang-format on

CrossfireModuleStatus crossfireModuleStatus[2] = {0};

const CrossfireSensor & getCrossfireSensor(uint8_t id, uint8_t subId)
{
if (id == LINK_ID)
Expand Down Expand Up @@ -260,6 +261,18 @@ void processCrossfireTelemetryFrame(uint8_t module, uint8_t* rxBuffer,

#if defined(LUA)
default:
if (id == DEVICE_INFO_ID && rxBuffer[4]== MODULE_ADDRESS) {
uint8_t nameSize = rxBuffer[1] - 18;
strncpy((char *)&crossfireModuleStatus[module].name, (const char *)&rxBuffer[5], CRSF_NAME_MAXSIZE);
crossfireModuleStatus[module].name[CRSF_NAME_MAXSIZE -1] = 0; // For some reason, GH din't like strlcpy
if (strncmp((const char *) &rxBuffer[5 + nameSize], "ELRS", 4) == 0)
crossfireModuleStatus[module].isELRS = true;
crossfireModuleStatus[module].major = rxBuffer[14 + nameSize];
crossfireModuleStatus[module].minor = rxBuffer[15 + nameSize];
crossfireModuleStatus[module].revision = rxBuffer[16 + nameSize];
crossfireModuleStatus[module].queryCompleted = true;
}

if (luaInputTelemetryFifo && luaInputTelemetryFifo->hasSpace(rxBufferCount - 2)) {
for (uint8_t i = 1; i < rxBufferCount - 1; i++) {
// destination address and CRC are skipped
Expand Down
Loading

0 comments on commit d454509

Please sign in to comment.