Co-authored-by: raphaelcoeffic <1050031+raphaelcoeffic@users.noreply.github.com> Co-authored-by: Peter Feerick <peter.feerick@gmail.com>
640 lines
17 KiB
C++
640 lines
17 KiB
C++
/*
|
|
* 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 "hal/module_port.h"
|
|
#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"
|
|
#include "dataconstants.h"
|
|
|
|
#if defined (HARDWARE_INTERNAL_MODULE)
|
|
#if defined(INTMODULE_USART)
|
|
|
|
#define INTMODULE_USART_IRQ_PRIORITY 5
|
|
|
|
static const stm32_usart_t intmoduleUSART = {
|
|
.USARTx = INTMODULE_USART,
|
|
.GPIOx = INTMODULE_GPIO,
|
|
.GPIO_Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN,
|
|
.IRQn = INTMODULE_USART_IRQn,
|
|
.IRQ_Prio = INTMODULE_USART_IRQ_PRIORITY,
|
|
#if defined(INTMODULE_DMA)
|
|
.txDMA = INTMODULE_DMA,
|
|
.txDMA_Stream = INTMODULE_DMA_STREAM,
|
|
.txDMA_Channel = INTMODULE_DMA_CHANNEL,
|
|
#else
|
|
.txDMA = nullptr,
|
|
.txDMA_Stream = 0,
|
|
.txDMA_Channel = 0,
|
|
#endif
|
|
#if defined(INTMODULE_RX_DMA)
|
|
.rxDMA = INTMODULE_RX_DMA,
|
|
.rxDMA_Stream = INTMODULE_RX_DMA_STREAM,
|
|
.rxDMA_Channel = INTMODULE_RX_DMA_CHANNEL,
|
|
#else
|
|
.rxDMA = nullptr,
|
|
.rxDMA_Stream = 0,
|
|
.rxDMA_Channel = 0,
|
|
#endif
|
|
};
|
|
|
|
DEFINE_STM32_SERIAL_PORT(InternalModule, intmoduleUSART, INTMODULE_FIFO_SIZE, 0);
|
|
|
|
#else // INTMODULE_USART
|
|
|
|
#include "stm32_pulse_driver.h"
|
|
#include "timers_driver.h"
|
|
|
|
static stm32_pulse_dma_tc_cb_t _int_timer_DMA_TC_Callback;
|
|
|
|
static const stm32_pulse_timer_t intmoduleTimer = {
|
|
.GPIOx = INTMODULE_TX_GPIO,
|
|
.GPIO_Pin = INTMODULE_TX_GPIO_PIN,
|
|
.GPIO_Alternate = INTMODULE_TX_GPIO_AF,
|
|
.TIMx = INTMODULE_TIMER,
|
|
.TIM_Freq = INTMODULE_TIMER_FREQ,
|
|
.TIM_Channel = INTMODULE_TIMER_Channel,
|
|
.TIM_IRQn = INTMODULE_TIMER_IRQn,
|
|
.DMAx = INTMODULE_TIMER_DMA,
|
|
.DMA_Stream = INTMODULE_TIMER_DMA_STREAM,
|
|
.DMA_Channel = INTMODULE_TIMER_DMA_CHANNEL,
|
|
.DMA_IRQn = INTMODULE_TIMER_DMA_STREAM_IRQn,
|
|
.DMA_TC_CallbackPtr = &_int_timer_DMA_TC_Callback,
|
|
};
|
|
|
|
// Make sure the timer channel is supported
|
|
static_assert(__STM32_PULSE_IS_TIMER_CHANNEL_SUPPORTED(INTMODULE_TIMER_Channel),
|
|
"Unsupported timer channel");
|
|
|
|
// Make sure the DMA channel is supported
|
|
static_assert(__STM32_DMA_IS_STREAM_SUPPORTED(INTMODULE_TIMER_DMA_STREAM),
|
|
"Unsupported DMA stream");
|
|
|
|
#if !defined(INTMODULE_TIMER_DMA_IRQHandler)
|
|
#error "Missing INTMODULE_TIMER_DMA_IRQHandler definition"
|
|
#endif
|
|
|
|
extern "C" void INTMODULE_TIMER_DMA_IRQHandler()
|
|
{
|
|
stm32_pulse_dma_tc_isr(&intmoduleTimer);
|
|
}
|
|
|
|
#if !defined(INTMODULE_TIMER_IRQHandler)
|
|
#error "Missing INTMODULE_TIMER_IRQHandler definition"
|
|
#endif
|
|
|
|
extern "C" void INTMODULE_TIMER_IRQHandler()
|
|
{
|
|
stm32_pulse_tim_update_isr(&intmoduleTimer);
|
|
}
|
|
|
|
DEFINE_STM32_SOFTSERIAL_PORT(InternalModule, intmoduleTimer);
|
|
|
|
#endif // INTMODULE_USART
|
|
#endif // HARDWARE_INTERNAL_MODULE
|
|
|
|
#include "module_timer_driver.h"
|
|
|
|
#if defined(HARDWARE_EXTERNAL_MODULE)
|
|
#if defined(EXTMODULE_USART)
|
|
|
|
#define EXTMODULE_USART_IRQ_PRIORITY 6
|
|
|
|
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
|
|
static void _extmod_set_inverted(uint8_t enable)
|
|
{
|
|
// In EdgeTX the external module is normally always
|
|
// inverted, so invert the logic here
|
|
if (!enable) {
|
|
LL_GPIO_SetOutputPin(EXTMODULE_TX_INVERT_GPIO,
|
|
EXTMODULE_TX_INVERT_GPIO_PIN);
|
|
LL_GPIO_SetOutputPin(EXTMODULE_RX_INVERT_GPIO,
|
|
EXTMODULE_RX_INVERT_GPIO_PIN);
|
|
} else {
|
|
LL_GPIO_ResetOutputPin(EXTMODULE_TX_INVERT_GPIO,
|
|
EXTMODULE_TX_INVERT_GPIO_PIN);
|
|
LL_GPIO_ResetOutputPin(EXTMODULE_RX_INVERT_GPIO,
|
|
EXTMODULE_RX_INVERT_GPIO_PIN);
|
|
}
|
|
}
|
|
|
|
static void _extmod_init_inverter()
|
|
{
|
|
LL_GPIO_InitTypeDef pinInit;
|
|
LL_GPIO_StructInit(&pinInit);
|
|
|
|
pinInit.Mode = LL_GPIO_MODE_OUTPUT;
|
|
pinInit.Pin = EXTMODULE_TX_INVERT_GPIO_PIN;
|
|
LL_GPIO_Init(EXTMODULE_TX_INVERT_GPIO, &pinInit);
|
|
|
|
pinInit.Pin = EXTMODULE_RX_INVERT_GPIO_PIN;
|
|
LL_GPIO_Init(EXTMODULE_RX_INVERT_GPIO, &pinInit);
|
|
|
|
// this sets the output to idle-low as is
|
|
// the default in EdgeTX on external module
|
|
// (historically, most radios work this way)
|
|
_extmod_set_inverted(false);
|
|
}
|
|
#endif
|
|
|
|
static const stm32_usart_t extmoduleUSART = {
|
|
.USARTx = EXTMODULE_USART,
|
|
.GPIOx = EXTMODULE_TX_GPIO,
|
|
.GPIO_Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN,
|
|
.IRQn = EXTMODULE_USART_IRQn,
|
|
.IRQ_Prio = EXTMODULE_USART_IRQ_PRIORITY,
|
|
.txDMA = EXTMODULE_USART_TX_DMA,
|
|
.txDMA_Stream = EXTMODULE_USART_TX_DMA_STREAM_LL,
|
|
.txDMA_Channel = EXTMODULE_USART_TX_DMA_CHANNEL,
|
|
.rxDMA = EXTMODULE_USART_TX_DMA,
|
|
.rxDMA_Stream = EXTMODULE_USART_RX_DMA_STREAM_LL,
|
|
.rxDMA_Channel = EXTMODULE_USART_RX_DMA_CHANNEL,
|
|
.set_input = nullptr,
|
|
.txDMA_IRQn = (IRQn_Type)0,
|
|
.txDMA_IRQ_Prio = 0,
|
|
};
|
|
|
|
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;
|
|
|
|
static const stm32_pulse_timer_t extmoduleTimer = {
|
|
.GPIOx = EXTMODULE_TX_GPIO,
|
|
.GPIO_Pin = EXTMODULE_TX_GPIO_PIN,
|
|
.GPIO_Alternate = EXTMODULE_TIMER_TX_GPIO_AF,
|
|
.TIMx = EXTMODULE_TIMER,
|
|
.TIM_Freq = EXTMODULE_TIMER_FREQ,
|
|
.TIM_Channel = EXTMODULE_TIMER_Channel,
|
|
.TIM_IRQn = EXTMODULE_TIMER_IRQn,
|
|
.DMAx = EXTMODULE_TIMER_DMA,
|
|
.DMA_Stream = EXTMODULE_TIMER_DMA_STREAM_LL,
|
|
.DMA_Channel = EXTMODULE_TIMER_DMA_CHANNEL,
|
|
.DMA_IRQn = EXTMODULE_TIMER_DMA_STREAM_IRQn,
|
|
.DMA_TC_CallbackPtr = &_ext_timer_DMA_TC_Callback,
|
|
};
|
|
|
|
// Make sure the timer channel is supported
|
|
static_assert(__STM32_PULSE_IS_TIMER_CHANNEL_SUPPORTED(EXTMODULE_TIMER_Channel),
|
|
"Unsupported timer channel");
|
|
|
|
// Make sure the DMA channel is supported
|
|
static_assert(__STM32_DMA_IS_STREAM_SUPPORTED(EXTMODULE_TIMER_DMA_STREAM_LL),
|
|
"Unsupported DMA stream");
|
|
|
|
#if !defined(EXTMODULE_TIMER_DMA_IRQHandler)
|
|
#error "Missing EXTMODULE_TIMER_DMA_IRQHandler definition"
|
|
#endif
|
|
|
|
extern "C" void EXTMODULE_TIMER_DMA_IRQHandler()
|
|
{
|
|
stm32_pulse_dma_tc_isr(&extmoduleTimer);
|
|
}
|
|
|
|
#if !defined(EXTMODULE_TIMER_IRQHandler)
|
|
#error "Missing EXTMODULE_TIMER_IRQHandler definition"
|
|
#endif
|
|
|
|
extern "C" void EXTMODULE_TIMER_IRQHandler()
|
|
{
|
|
stm32_pulse_tim_update_isr(&extmoduleTimer);
|
|
}
|
|
|
|
DEFINE_STM32_SOFTSERIAL_PORT(ExternalModule, extmoduleTimer);
|
|
|
|
#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
|
|
|
|
static void _set_sport_input(uint8_t enable)
|
|
{
|
|
if (TELEMETRY_SET_INPUT) {
|
|
if (enable) {
|
|
LL_GPIO_SetOutputPin(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
|
|
} else {
|
|
LL_GPIO_ResetOutputPin(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
|
|
}
|
|
} else {
|
|
if (enable) {
|
|
LL_GPIO_ResetOutputPin(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
|
|
} else {
|
|
LL_GPIO_SetOutputPin(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined(TELEMETRY_REV_GPIO)
|
|
static void _sport_set_inverted(uint8_t enable)
|
|
{
|
|
uint32_t pins = TELEMETRY_TX_REV_GPIO_PIN | TELEMETRY_RX_REV_GPIO_PIN;
|
|
if (!enable) {
|
|
LL_GPIO_SetOutputPin(TELEMETRY_REV_GPIO, pins);
|
|
} else {
|
|
LL_GPIO_ResetOutputPin(TELEMETRY_REV_GPIO, pins);
|
|
}
|
|
}
|
|
|
|
static void _sport_init_inverter()
|
|
{
|
|
LL_GPIO_InitTypeDef pinInit;
|
|
LL_GPIO_StructInit(&pinInit);
|
|
|
|
pinInit.Pin = TELEMETRY_TX_REV_GPIO_PIN | TELEMETRY_RX_REV_GPIO_PIN;
|
|
pinInit.Mode = LL_GPIO_MODE_OUTPUT;
|
|
LL_GPIO_Init(TELEMETRY_REV_GPIO, &pinInit);
|
|
_sport_set_inverted(false);
|
|
}
|
|
#endif
|
|
|
|
static const stm32_usart_t sportUSART = {
|
|
.USARTx = TELEMETRY_USART,
|
|
.GPIOx = TELEMETRY_GPIO,
|
|
.GPIO_Pin = TELEMETRY_TX_GPIO_PIN | TELEMETRY_RX_GPIO_PIN,
|
|
.IRQn = TELEMETRY_USART_IRQn,
|
|
.IRQ_Prio = TELEMETRY_USART_IRQ_PRIORITY,
|
|
.txDMA = TELEMETRY_DMA,
|
|
.txDMA_Stream = TELEMETRY_DMA_Stream_TX,
|
|
.txDMA_Channel = TELEMETRY_DMA_Channel_TX,
|
|
.rxDMA = nullptr,
|
|
.rxDMA_Stream = 0,
|
|
.rxDMA_Channel = 0,
|
|
.set_input = _set_sport_input,
|
|
.txDMA_IRQn = TELEMETRY_DMA_TX_Stream_IRQ,
|
|
.txDMA_IRQ_Prio = TELEMETRY_DMA_IRQ_PRIORITY,
|
|
};
|
|
|
|
extern "C" void TELEMETRY_DMA_TX_IRQHandler(void)
|
|
{
|
|
stm32_usart_tx_dma_isr(&sportUSART);
|
|
}
|
|
|
|
DEFINE_STM32_SERIAL_PORT(SportModule, sportUSART, TELEMETRY_FIFO_SIZE, 0);
|
|
|
|
static void _sport_direction_init()
|
|
{
|
|
LL_GPIO_InitTypeDef dirPinInit;
|
|
LL_GPIO_StructInit(&dirPinInit);
|
|
|
|
dirPinInit.Pin = TELEMETRY_DIR_GPIO_PIN;
|
|
dirPinInit.Mode = LL_GPIO_MODE_OUTPUT;
|
|
LL_GPIO_Init(TELEMETRY_DIR_GPIO, &dirPinInit);
|
|
}
|
|
|
|
#if defined(TELEMETRY_TIMER)
|
|
static const stm32_softserial_rx_port sportSoftRX = {
|
|
.GPIOx = TELEMETRY_GPIO,
|
|
.GPIO_Pin = TELEMETRY_RX_GPIO_PIN,
|
|
.TIMx = TELEMETRY_TIMER,
|
|
.TIM_Freq = PERI2_FREQUENCY * TIMER_MULT_APB2,
|
|
.TIM_IRQn = TELEMETRY_TIMER_IRQn,
|
|
.EXTI_Port = TELEMETRY_EXTI_PORT,
|
|
.EXTI_SysLine = TELEMETRY_EXTI_SYS_LINE,
|
|
.EXTI_Line = TELEMETRY_EXTI_LINE,
|
|
.dir_GPIOx = TELEMETRY_DIR_GPIO,
|
|
.dir_Pin = TELEMETRY_DIR_GPIO_PIN,
|
|
.dir_Input = TELEMETRY_SET_INPUT,
|
|
// re-use S.PORT serial RX buffer
|
|
.buffer = { SportModule_RXBuffer, TELEMETRY_FIFO_SIZE },
|
|
};
|
|
|
|
extern "C" void TELEMETRY_TIMER_IRQHandler()
|
|
{
|
|
stm32_softserial_rx_timer_isr(&sportSoftRX);
|
|
}
|
|
#endif
|
|
|
|
#if defined(HARDWARE_INTERNAL_MODULE)
|
|
|
|
static void _internal_module_set_pwr(uint8_t enable)
|
|
{
|
|
if (enable) {
|
|
INTERNAL_MODULE_ON();
|
|
} else {
|
|
INTERNAL_MODULE_OFF();
|
|
}
|
|
}
|
|
|
|
#if defined(INTMODULE_BOOTCMD_GPIO)
|
|
static void _internal_module_set_bootcmd(uint8_t enable)
|
|
{
|
|
// If default state is SET, invert the logic
|
|
if (INTMODULE_BOOTCMD_DEFAULT) {
|
|
enable = !enable;
|
|
}
|
|
|
|
if (enable) {
|
|
LL_GPIO_SetOutputPin(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
|
|
} else {
|
|
LL_GPIO_ResetOutputPin(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static const etx_module_port_t _internal_ports[] = {
|
|
#if defined(INTMODULE_USART)
|
|
{
|
|
.port = ETX_MOD_PORT_UART,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_TX_RX | ETX_MOD_FULL_DUPLEX,
|
|
.drv = { .serial = &STM32SerialDriver },
|
|
.hw_def = REF_STM32_SERIAL_PORT(InternalModule),
|
|
},
|
|
#else // INTMODULE_USART
|
|
{
|
|
.port = ETX_MOD_PORT_SOFT_INV,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_TX,
|
|
.drv = { .serial = &STM32SoftSerialTxDriver },
|
|
.hw_def = REF_STM32_SOFTSERIAL_PORT(InternalModule),
|
|
},
|
|
#endif
|
|
#if defined(INTERNAL_MODULE_PXX1)
|
|
{
|
|
.port = ETX_MOD_PORT_SPORT,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_TX | ETX_MOD_DIR_RX,
|
|
.drv = { .serial = &STM32SerialDriver },
|
|
.hw_def = REF_STM32_SERIAL_PORT(SportModule),
|
|
},
|
|
#endif
|
|
};
|
|
|
|
static const etx_module_t _internal_module = {
|
|
.ports = _internal_ports,
|
|
.set_pwr = _internal_module_set_pwr,
|
|
#if defined(INTMODULE_BOOTCMD_GPIO)
|
|
.set_bootcmd = _internal_module_set_bootcmd,
|
|
#else
|
|
.set_bootcmd = nullptr,
|
|
#endif
|
|
.n_ports = DIM(_internal_ports),
|
|
};
|
|
#endif
|
|
|
|
#if defined(HARDWARE_EXTERNAL_MODULE)
|
|
|
|
static void _external_module_set_pwr(uint8_t enable)
|
|
{
|
|
if (enable) {
|
|
EXTERNAL_MODULE_ON();
|
|
#if defined(PCBNV14)
|
|
if (hardwareOptions.pcbrev == PCBREV_NV14) {
|
|
LL_GPIO_ResetOutputPin(EXTMODULE_PWR_FIX_GPIO, EXTMODULE_PWR_FIX_GPIO_PIN);
|
|
}
|
|
#endif
|
|
} else {
|
|
EXTERNAL_MODULE_OFF();
|
|
#if defined(PCBNV14)
|
|
if (hardwareOptions.pcbrev == PCBREV_NV14) {
|
|
LL_GPIO_SetOutputPin(EXTMODULE_PWR_FIX_GPIO, EXTMODULE_PWR_FIX_GPIO_PIN);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static const etx_module_port_t _external_ports[] = {
|
|
#if defined(EXTMODULE_USART)
|
|
// TX on PPM, RX on HEARTBEAT
|
|
{
|
|
.port = ETX_MOD_PORT_UART,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_TX_RX | ETX_MOD_FULL_DUPLEX,
|
|
.drv = { .serial = &STM32SerialDriver },
|
|
.hw_def = REF_STM32_SERIAL_PORT(ExternalModule),
|
|
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
|
|
.set_inverted = _extmod_set_inverted,
|
|
#else
|
|
.set_inverted = nullptr,
|
|
#endif
|
|
},
|
|
#endif
|
|
// Timer output on PPM
|
|
{
|
|
.port = ETX_MOD_PORT_TIMER,
|
|
.type = ETX_MOD_TYPE_TIMER,
|
|
.dir_flags = ETX_MOD_DIR_TX,
|
|
.drv = { .timer = &STM32ModuleTimerDriver },
|
|
.hw_def = (void*)&extmoduleTimer,
|
|
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
|
|
.set_inverted = _extmod_set_inverted,
|
|
#else
|
|
.set_inverted = nullptr,
|
|
#endif
|
|
},
|
|
// TX inverted DMA pulse train on PPM
|
|
{
|
|
.port = ETX_MOD_PORT_SOFT_INV,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_TX,
|
|
.drv = { .serial = &STM32SoftSerialTxDriver },
|
|
.hw_def = REF_STM32_SOFTSERIAL_PORT(ExternalModule),
|
|
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
|
|
.set_inverted = _extmod_set_inverted,
|
|
#else
|
|
.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,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_TX | ETX_MOD_DIR_RX,
|
|
.drv = { .serial = &STM32SerialDriver },
|
|
.hw_def = REF_STM32_SERIAL_PORT(SportModule),
|
|
#if defined(TELEMETRY_REV_GPIO)
|
|
.set_inverted = _sport_set_inverted,
|
|
#else
|
|
.set_inverted = nullptr,
|
|
#endif
|
|
},
|
|
#if defined(TELEMETRY_TIMER)
|
|
// RX soft-serial sampled bit-by-bit via timer IRQ on S.PORT
|
|
{
|
|
.port = ETX_MOD_PORT_SPORT_INV,
|
|
.type = ETX_MOD_TYPE_SERIAL,
|
|
.dir_flags = ETX_MOD_DIR_RX,
|
|
.drv = { .serial = &STM32SoftSerialRxDriver },
|
|
.hw_def = (void*)&sportSoftRX,
|
|
},
|
|
#endif
|
|
};
|
|
|
|
static const etx_module_t _external_module = {
|
|
.ports = _external_ports,
|
|
.set_pwr = _external_module_set_pwr,
|
|
.set_bootcmd = nullptr,
|
|
.n_ports = DIM(_external_ports),
|
|
};
|
|
#endif
|
|
|
|
#if defined(SPORT_UPDATE_PWR_GPIO)
|
|
#include "sport_update.h"
|
|
|
|
// Not declared 'static' to be accessible
|
|
// from board.cpp
|
|
void _sport_set_pwr(uint8_t enabled)
|
|
{
|
|
if (enabled) {
|
|
LL_GPIO_SetOutputPin(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN);
|
|
} else {
|
|
LL_GPIO_ResetOutputPin(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN);
|
|
}
|
|
}
|
|
|
|
#if defined(RADIO_X7)
|
|
// set_pwr is set at runtime once
|
|
// the PCB has been identified
|
|
etx_module_t _sport_module = {
|
|
.ports = nullptr,
|
|
.set_pwr = nullptr,
|
|
.set_bootcmd = nullptr,
|
|
.n_ports = 0,
|
|
};
|
|
#else
|
|
const etx_module_t _sport_module = {
|
|
.ports = nullptr,
|
|
.set_pwr = _sport_set_pwr,
|
|
.set_bootcmd = nullptr,
|
|
.n_ports = 0,
|
|
};
|
|
#endif // RADIO_X7
|
|
|
|
#endif // SPORT_UPDATE_PWR_GPIO
|
|
|
|
#if !defined(RADIO_X10E)
|
|
uint32_t __pxx1_get_inverter_comp() { return 1; }
|
|
#endif
|
|
|
|
void boardInitModulePorts()
|
|
{
|
|
_sport_direction_init();
|
|
#if defined(SPORT_UPDATE_PWR_GPIO)
|
|
sportUpdateInit();
|
|
#endif
|
|
|
|
#if defined(TELEMETRY_REV_GPIO)
|
|
_sport_init_inverter();
|
|
#endif
|
|
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
|
|
_extmod_init_inverter();
|
|
#endif
|
|
|
|
#if defined(PCBNV14)
|
|
if (hardwareOptions.pcbrev == PCBREV_NV14) {
|
|
LL_GPIO_InitTypeDef pinInit;
|
|
LL_GPIO_StructInit(&pinInit);
|
|
pinInit.Pin = EXTMODULE_PWR_FIX_GPIO_PIN;
|
|
pinInit.Mode = LL_GPIO_MODE_OUTPUT;
|
|
|
|
// pin must be pulled to V+ (voltage of board - VCC is not enough to fully close transistor)
|
|
// for additional transistor to ensuring module is completely disabled
|
|
pinInit.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
|
|
|
|
LL_GPIO_SetOutputPin(EXTMODULE_PWR_FIX_GPIO, EXTMODULE_PWR_FIX_GPIO_PIN);
|
|
LL_GPIO_Init(EXTMODULE_PWR_FIX_GPIO, &pinInit);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BEGIN_MODULES()
|
|
#if defined(HARDWARE_INTERNAL_MODULE)
|
|
&_internal_module,
|
|
#else
|
|
nullptr,
|
|
#endif
|
|
#if defined(HARDWARE_EXTERNAL_MODULE)
|
|
&_external_module,
|
|
#else
|
|
nullptr,
|
|
#endif
|
|
#if defined(SPORT_UPDATE_PWR_GPIO)
|
|
&_sport_module,
|
|
#endif
|
|
END_MODULES()
|