Skip to content

Commit

Permalink
feat(radio): Discover SBUS trainer availability (#4266)
Browse files Browse the repository at this point in the history
Co-authored-by: raphaelcoeffic <[email protected]>
Co-authored-by: Peter Feerick <[email protected]>
  • Loading branch information
3 people authored Jan 5, 2024
1 parent b22fa28 commit fa12b27
Show file tree
Hide file tree
Showing 39 changed files with 571 additions and 463 deletions.
3 changes: 2 additions & 1 deletion radio/src/bluetooth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "opentx.h"
#include "io/frsky_firmware_update.h"
#include "bluetooth_driver.h"
#include "trainer.h"

#if defined(LIBOPENUI)
#include "libopenui.h"
Expand Down Expand Up @@ -145,7 +146,7 @@ void Bluetooth::processTrainerFrame(const uint8_t * buffer)
trainerInput[channel+1] = ((buffer[i+1] & 0x0f) << 4) + ((buffer[i+2] & 0xf0) >> 4) + ((buffer[i+2] & 0x0f) << 8) - 1500;
}

trainerInputValidityTimer = TRAINER_IN_VALID_TIMEOUT;
trainerResetTimer();
}

void Bluetooth::appendTrainerByte(uint8_t data)
Expand Down
1 change: 1 addition & 0 deletions radio/src/boards/generic_stm32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(BOARD_LIB_SRC
${CMAKE_CURRENT_BINARY_DIR}/hal_adc_inputs.inc

boards/generic_stm32/module_ports.cpp
boards/generic_stm32/trainer_ports.cpp
boards/generic_stm32/aux_ports.cpp
boards/generic_stm32/sport_update.cpp
boards/generic_stm32/intmodule_heartbeat.cpp
Expand Down
35 changes: 35 additions & 0 deletions radio/src/boards/generic_stm32/intmodule_heartbeat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@
#include "heartbeat_driver.h"
#include "mixer_scheduler.h"
#include "dataconstants.h"

#include "pulses/pxx.h"
#include "trainer.h"

#include "opentx.h"
#include "pulses/pulses.h"

#if defined(PXX1)
#include "pulses/pxx1.h"
Expand All @@ -40,9 +45,21 @@
#define isPxx2Driver(drv) (false)
#endif

static bool _trainer_mode_uses_ext_module(uint8_t mode)
{
return mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE ||
mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE;
}

void _intmodule_heartbeat_init(uint8_t module, const etx_proto_driver_t* drv)
{
if (module == INTERNAL_MODULE && (isPxx1Driver(drv) || isPxx2Driver(drv))) {

// heartbeat cannot be used if the trainer is using the module bay
if (_trainer_mode_uses_ext_module(currentTrainerMode)) {
return;
}

init_intmodule_heartbeat();
if (isPxx1Driver(drv)) {
// XJT / iXJT
Expand All @@ -61,3 +78,21 @@ void _intmodule_heartbeat_deinit(uint8_t module, const etx_proto_driver_t* drv)
stop_intmodule_heartbeat();
}
}

void _intmodule_heartbeat_trainer_hook(uint8_t old_mode, uint8_t new_mode)
{
bool restart_int_module = false;

if (_trainer_mode_uses_ext_module(new_mode)) {
restart_int_module = true;
} else if (_trainer_mode_uses_ext_module(old_mode)) {
restart_int_module = true;
}

if (restart_int_module) {
auto pdrv = pulsesGetModuleDriver(INTERNAL_MODULE);
if (pdrv && (isPxx2Driver(pdrv->drv) || isPxx1Driver(pdrv->drv))) {
restartModule(INTERNAL_MODULE);
}
}
}
2 changes: 1 addition & 1 deletion radio/src/boards/generic_stm32/intmodule_heartbeat.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@

void _intmodule_heartbeat_init(uint8_t module, const etx_proto_driver_t* drv);
void _intmodule_heartbeat_deinit(uint8_t module, const etx_proto_driver_t* drv);

void _intmodule_heartbeat_trainer_hook(uint8_t old_mode, uint8_t new_mode);
66 changes: 65 additions & 1 deletion radio/src/boards/generic_stm32/module_ports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "stm32_serial_driver.h"
#include "stm32_softserial_driver.h"
#include "stm32_dma.h"
#include "trainer_driver.h"

#include "module_ports.h"
#include "board.h"
Expand Down Expand Up @@ -177,6 +178,24 @@ static const stm32_usart_t extmoduleUSART = {

DEFINE_STM32_SERIAL_PORT(ExternalModule, extmoduleUSART, INTMODULE_FIFO_SIZE, 0);

#elif defined(TRAINER_MODULE_SBUS_USART)

static const stm32_usart_t sbus_trainer_USART = {
.USARTx = TRAINER_MODULE_SBUS_USART,
.GPIOx = TRAINER_MODULE_SBUS_GPIO,
.GPIO_Pin = TRAINER_MODULE_SBUS_GPIO_PIN,
.IRQn = (IRQn_Type)-1,
.IRQ_Prio = 0,
.txDMA = nullptr,
.txDMA_Stream = 0,
.txDMA_Channel = 0,
.rxDMA = TRAINER_MODULE_SBUS_DMA,
.rxDMA_Stream = TRAINER_MODULE_SBUS_DMA_STREAM_LL,
.rxDMA_Channel = TRAINER_MODULE_SBUS_DMA_CHANNEL,
};

DEFINE_STM32_SERIAL_PORT(SbusTrainer, sbus_trainer_USART, 32, 0);

#endif

static stm32_pulse_dma_tc_cb_t _ext_timer_DMA_TC_Callback;
Expand Down Expand Up @@ -223,7 +242,30 @@ extern "C" void EXTMODULE_TIMER_IRQHandler()
}

DEFINE_STM32_SOFTSERIAL_PORT(ExternalModule, extmoduleTimer);
#endif

#if defined(TRAINER_MODULE_CPPM_TIMER)

static_assert(__IS_TRAINER_TIMER_IN_CHANNEL_SUPPORTED(TRAINER_MODULE_CPPM_TIMER_Channel),
"Unsupported trainer timer input channel");

static const stm32_pulse_timer_t trainerModuleTimer = {
.GPIOx = TRAINER_MODULE_CPPM_GPIO,
.GPIO_Pin = TRAINER_MODULE_CPPM_GPIO_PIN,
.GPIO_Alternate = TRAINER_MODULE_CPPM_GPIO_AF,
.TIMx = TRAINER_MODULE_CPPM_TIMER,
.TIM_Freq = TRAINER_MODULE_CPPM_FREQ,
.TIM_Channel = TRAINER_MODULE_CPPM_TIMER_Channel,
.TIM_IRQn = TRAINER_MODULE_CPPM_TIMER_IRQn,
.DMAx = nullptr,
.DMA_Stream = 0,
.DMA_Channel = 0,
.DMA_IRQn = (IRQn_Type)0,
.DMA_TC_CallbackPtr = nullptr,
};

#endif // TRAINER_MODULE_CPPM_TIMER

#endif // HARDWARE_EXTERNAL_MODULE

#define TELEMETRY_USART_IRQ_PRIORITY 0
#define TELEMETRY_DMA_IRQ_PRIORITY 0
Expand Down Expand Up @@ -456,6 +498,28 @@ static const etx_module_port_t _external_ports[] = {
.set_inverted = nullptr,
#endif
},
#if !defined(EXTMODULE_USART) && defined(TRAINER_MODULE_SBUS_USART)
// RX on HEARTBEAT
{
.port = ETX_MOD_PORT_UART,
.type = ETX_MOD_TYPE_SERIAL,
.dir_flags = ETX_MOD_DIR_RX,
.drv = { .serial = &STM32SerialDriver },
.hw_def = REF_STM32_SERIAL_PORT(SbusTrainer),
.set_inverted = nullptr,
},
#endif
#if defined(TRAINER_MODULE_CPPM_TIMER)
// Timer input on HEARTBEAT
{
.port = ETX_MOD_PORT_TIMER,
.type = ETX_MOD_TYPE_TIMER,
.dir_flags = ETX_MOD_DIR_RX,
.drv = { .timer = nullptr },
.hw_def = (void*)&trainerModuleTimer,
.set_inverted = nullptr,
},
#endif
// TX/RX half-duplex on S.PORT
{
.port = ETX_MOD_PORT_SPORT,
Expand Down
147 changes: 147 additions & 0 deletions radio/src/boards/generic_stm32/trainer_ports.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#include "stm32_pulse_driver.h"
#include "stm32_gpio_driver.h"
#include "trainer_driver.h"

#include "hal/module_port.h"
#include "dataconstants.h"

#include "hal.h"

void board_trainer_init()
{
#if defined(TRAINER_DETECT_GPIO_PIN)
LL_GPIO_InitTypeDef pinInit;
LL_GPIO_StructInit(&pinInit);

pinInit.Pin = TRAINER_DETECT_GPIO_PIN;
pinInit.Mode = LL_GPIO_MODE_INPUT;
pinInit.Pull = LL_GPIO_PULL_UP;
stm32_gpio_enable_clock(TRAINER_DETECT_GPIO);
LL_GPIO_Init(TRAINER_DETECT_GPIO, &pinInit);
#endif

trainer_init();
}

#if defined(TRAINER_GPIO)

bool trainer_dsc_available() { return true; }

static_assert(__IS_TRAINER_TIMER_OUT_CHANNEL_SUPPORTED(TRAINER_OUT_TIMER_Channel),
"Unsupported trainer timer output channel");

static_assert(__IS_TRAINER_TIMER_IN_CHANNEL_SUPPORTED(TRAINER_IN_TIMER_Channel),
"Unsupported trainer timer input channel");

static const stm32_pulse_timer_t trainerOutputTimer = {
.GPIOx = TRAINER_GPIO,
.GPIO_Pin = TRAINER_OUT_GPIO_PIN,
.GPIO_Alternate = TRAINER_GPIO_AF,
.TIMx = TRAINER_TIMER,
.TIM_Freq = TRAINER_TIMER_FREQ,
.TIM_Channel = TRAINER_OUT_TIMER_Channel,
.TIM_IRQn = TRAINER_TIMER_IRQn,
.DMAx = nullptr,
.DMA_Stream = 0,
.DMA_Channel = 0,
.DMA_IRQn = (IRQn_Type)0,
.DMA_TC_CallbackPtr = nullptr,
};

void trainer_init_dsc_out()
{
trainer_init_output(&trainerOutputTimer);
}

static const stm32_pulse_timer_t trainerInputTimer = {
.GPIOx = TRAINER_GPIO,
.GPIO_Pin = TRAINER_IN_GPIO_PIN,
.GPIO_Alternate = TRAINER_GPIO_AF,
.TIMx = TRAINER_TIMER,
.TIM_Freq = TRAINER_TIMER_FREQ,
.TIM_Channel = TRAINER_IN_TIMER_Channel,
.TIM_IRQn = TRAINER_TIMER_IRQn,
.DMAx = nullptr,
.DMA_Stream = 0,
.DMA_Channel = 0,
.DMA_IRQn = (IRQn_Type)0,
.DMA_TC_CallbackPtr = nullptr,
};

void trainer_init_dsc_in()
{
trainer_init_capture(&trainerInputTimer);
}

void trainer_stop_dsc() { trainer_stop(); }

#else
bool trainer_dsc_available() { return false; }
void trainer_init_dsc_out() {}
void trainer_init_dsc_in() {}
void trainer_stop_dsc() {}
#endif

bool is_trainer_dsc_connected()
{
#if defined(TRAINER_DETECT_GPIO_PIN)
bool set = LL_GPIO_IsInputPinSet(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN);
#if defined(TRAINER_DETECT_INVERTED)
return !set;
#else
return set;
#endif
#else // TRAINER_DETECT_GPIO_PIN
return true;
#endif
}

void trainer_init_module_cppm()
{
auto port = modulePortFind(EXTERNAL_MODULE, ETX_MOD_TYPE_TIMER,
ETX_MOD_PORT_TIMER, ETX_Pol_Normal,
ETX_MOD_DIR_RX);
if (!port) return;

auto tim = (const stm32_pulse_timer_t*)port->hw_def;
if (!tim) return;

modulePortSetPower(EXTERNAL_MODULE,true);
trainer_init_capture(tim);
}

void trainer_stop_module_cppm()
{
trainer_stop();
modulePortSetPower(EXTERNAL_MODULE,false);
}

#if defined(TRAINER_TIMER_IRQHandler)
extern "C" void TRAINER_TIMER_IRQHandler() { trainer_timer_isr(); }
#endif

#if defined(TRAINER_MODULE_CPPM_TIMER_IRQHandler) && \
TRAINER_TIMER_IRQHandler != TRAINER_MODULE_CPPM_TIMER_IRQHandler
extern "C" void TRAINER_MODULE_CPPM_TIMER_IRQHandler() { trainer_timer_isr(); }
#endif
2 changes: 1 addition & 1 deletion radio/src/gui/212x64/view_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void displayTopBar()
x -= 12;
}
}
else if (is_trainer_connected()) {
else if (isTrainerConnected()) {
LCD_NOTIF_ICON(x, ICON_TRAINER);
x -= 12;
}
Expand Down
Loading

0 comments on commit fa12b27

Please sign in to comment.