fix: Internal PXX exclusive S.PORT (#3822)

This commit is contained in:
Raphael Coeffic
2023-10-13 09:48:32 +10:00
committed by GitHub
parent c270ec18bf
commit ff2b3ac22a
24 changed files with 435 additions and 186 deletions
+5 -3
View File
@@ -23,6 +23,7 @@
#include "mixer_scheduler.h"
#include "hal/adc_driver.h"
#include "hal/switch_driver.h"
#include "hal/module_port.h"
#include "switches.h"
#if defined(USBJ_EX)
@@ -1972,10 +1973,11 @@ void menuModelSetup(event_t event)
#endif
if (isModuleR9MNonAccess(moduleIdx)) {
lcdDrawTextAlignedLeft(y, STR_MODULE_TELEMETRY);
if (isSportLineUsedByInternalModule())
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL);
else
if (modulePortIsPortUsedByModule(moduleIdx, ETX_MOD_PORT_SPORT)) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON);
} else {
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL);
}
}
else if (isModuleSBUS(moduleIdx)) {
lcdDrawTextAlignedLeft(y, STR_WARN_BATTVOLTAGE);
+4 -3
View File
@@ -22,6 +22,7 @@
#include "hal/adc_driver.h"
#include "hal/adc_driver.h"
#include "hal/switch_driver.h"
#include "hal/module_port.h"
#include "opentx.h"
#include "mixer_scheduler.h"
@@ -1739,11 +1740,11 @@ void menuModelSetup(event_t event)
#endif
if (isModuleR9MNonAccess(moduleIdx)) {
lcdDrawTextAlignedLeft(y, STR_MODULE_TELEMETRY);
if (isSportLineUsedByInternalModule()) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL);
if (modulePortIsPortUsedByModule(moduleIdx, ETX_MOD_PORT_SPORT)) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON);
}
else {
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON);
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL);
}
}
else if (isModuleSBUS(moduleIdx)) {
+57 -10
View File
@@ -57,11 +57,14 @@ static void modulePortClear(etx_module_state_t* st)
memset(st, 0, sizeof(etx_module_state_t));
}
static void _init_serial_driver(etx_module_driver_t* d, const etx_module_port_t* port,
static bool _init_serial_driver(etx_module_driver_t* d, const etx_module_port_t* port,
const etx_serial_init* params)
{
auto drv = port->drv.serial;
d->ctx = drv->init(port->hw_def, params);
auto ctx = drv->init(port->hw_def, params);
if (!ctx) return false;
d->ctx = ctx;
d->port = port;
// S.PORT specific HW settings
@@ -80,19 +83,26 @@ static void _init_serial_driver(etx_module_driver_t* d, const etx_module_port_t*
if (port->set_inverted) {
port->set_inverted(params->polarity == ETX_Pol_Inverted);
}
return true;
}
static void _init_timer_driver(etx_module_driver_t* d, const etx_module_port_t* port,
static bool _init_timer_driver(etx_module_driver_t* d, const etx_module_port_t* port,
const etx_timer_config_t* cfg)
{
auto drv = port->drv.timer;
d->ctx = drv->init(port->hw_def, cfg);
auto ctx = drv->init(port->hw_def, cfg);
if (!ctx) return false;
d->ctx = ctx;
d->port = port;
// setup polarity
if (port->set_inverted) {
port->set_inverted(false);
}
return true;
}
static bool _match_port(const etx_module_port_t* p, uint8_t type, uint8_t port,
@@ -202,10 +212,11 @@ etx_module_state_t* modulePortInitSerial(uint8_t module, uint8_t port,
const uint8_t duplex = ETX_Dir_TX_RX;
uint8_t dir = params->direction & duplex;
bool init_ok = false;
if (dir == duplex) {
// init RX first, in case TX was already done previously
_init_serial_driver(&state->rx, found_port, params);
init_ok = _init_serial_driver(&state->rx, found_port, params);
// do not overwrite TX state if it has already been set:
// -> support using S.PORT in bidir mode
@@ -214,12 +225,12 @@ etx_module_state_t* modulePortInitSerial(uint8_t module, uint8_t port,
state->tx.ctx = state->rx.ctx;
}
} else if (dir == ETX_Dir_TX) {
_init_serial_driver(&state->tx, found_port, params);
init_ok = _init_serial_driver(&state->tx, found_port, params);
} else if (dir == ETX_Dir_RX) {
_init_serial_driver(&state->rx, found_port, params);
init_ok = _init_serial_driver(&state->rx, found_port, params);
}
return state;
return init_ok ? state : nullptr;
}
etx_module_state_t* modulePortInitTimer(uint8_t module, uint8_t port,
@@ -230,9 +241,9 @@ etx_module_state_t* modulePortInitTimer(uint8_t module, uint8_t port,
if (!found_port) return nullptr;
auto state = &(_module_states[module]);
_init_timer_driver(&state->tx, found_port, cfg);
bool init_ok = _init_timer_driver(&state->tx, found_port, cfg);
return state;
return init_ok ? state : nullptr;
}
static void _deinit_driver(etx_module_driver_t* d)
@@ -262,6 +273,14 @@ void modulePortDeInit(etx_module_state_t* st)
modulePortClear(st);
}
void modulePortDeInitRxPort(etx_module_state_t* st)
{
if (st->rx.port) {
_deinit_driver(&st->rx);
memset(&st->rx, 0, sizeof(etx_module_driver_t));
}
}
etx_module_state_t* modulePortGetState(uint8_t module)
{
if (module >= MAX_MODULES) return nullptr;
@@ -272,3 +291,31 @@ uint8_t modulePortGetModule(etx_module_state_t* st)
{
return st - _module_states;
}
bool modulePortIsPortUsedByModule(uint8_t module, uint8_t port)
{
auto mod_st = modulePortGetState(module);
if (!mod_st) return false;
auto tx_port = mod_st->tx.port;
auto rx_port = mod_st->rx.port;
return (tx_port && tx_port->port == port) ||
(rx_port && rx_port->port == port);
}
bool modulePortIsPortUsed(uint8_t port)
{
return modulePortGetModuleForPort(port) >= 0;
}
int8_t modulePortGetModuleForPort(uint8_t port)
{
for (uint8_t module = 0; module < MAX_MODULES; module++) {
if (modulePortIsPortUsedByModule(module, port)) {
return module;
}
}
return -1;
}
+7
View File
@@ -136,6 +136,9 @@ etx_module_state_t* modulePortInitTimer(uint8_t module, uint8_t port,
// De-init port and clear data
void modulePortDeInit(etx_module_state_t* st);
// De-init RX part
void modulePortDeInitRxPort(etx_module_state_t* st);
// Once initialized, retrieve module serial driver and context
etx_module_state_t* modulePortGetState(uint8_t module);
@@ -159,3 +162,7 @@ inline void* modulePortGetCtx(const etx_module_driver_t& d) {
return d.ctx;
}
bool modulePortIsPortUsedByModule(uint8_t module, uint8_t port);
bool modulePortIsPortUsed(uint8_t port);
int8_t modulePortGetModuleForPort(uint8_t port);
+2 -13
View File
@@ -28,6 +28,7 @@
#include "storage/storage.h"
#include "globals.h"
#include "MultiProtoDefs.h"
#include "hal/module_port.h"
#if defined(MULTIMODULE)
#include "telemetry/multi.h"
@@ -728,25 +729,13 @@ 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)
if (moduleIndex == INTERNAL_MODULE)
return true;
if (isSportLineUsedByInternalModule())
if (!modulePortIsPortUsedByModule(moduleIndex, ETX_MOD_PORT_SPORT))
return false;
#endif
+3 -3
View File
@@ -139,8 +139,8 @@ static void setupPulsesMulti(uint8_t*& p_buf, uint8_t module)
}
// Invert telemetry if needed
if (invert[module] & 0x80 &&
!g_model.moduleData[module].multi.disableTelemetry) {
uint8_t disableTelemetry = modulePortIsPortUsedByModule(module, ETX_MOD_PORT_SPORT) ? 0 : 1;
if (invert[module] & 0x80 && !disableTelemetry) {
if (getMultiModuleStatus(module).isValid()) {
invert[module] &= 0x08; // Telemetry received, stop searching
} else if (counter[module] % 100 == 0) {
@@ -170,7 +170,7 @@ static void setupPulsesMulti(uint8_t*& p_buf, uint8_t module)
| (g_model.header.modelId[module] & 0x30)
| (invert[module] & 0x08)
//| 0x04 // Future use
| (g_model.moduleData[module].multi.disableTelemetry << 1)
| (disableTelemetry << 1)
| g_model.moduleData[module].multi.disableMapping));
}
-17
View File
@@ -21,23 +21,6 @@
#pragma once
#include "pulses_common.h"
#include "hal/serial_driver.h"
#include "hal/module_driver.h"
class UartMultiPulses: public DataBuffer<uint8_t, 64>
{
public:
void initFrame()
{
initBuffer();
}
void sendByte(uint8_t b)
{
if (getSize() < 64)
*ptr++ = b;
}
};
extern const etx_proto_driver_t MultiDriver;
+13
View File
@@ -111,6 +111,19 @@ void restartModule(uint8_t module)
mixerTaskStart();
}
void pulsesRestartModuleUnsafe(uint8_t module)
{
if (module >= MAX_MODULES)
return;
auto mod_drv = pulsesGetModuleDriver(module);
if (!mod_drv->drv) return;
auto drv = mod_drv->drv;
drv->deinit(mod_drv->ctx);
mod_drv->ctx = drv->init(module);
}
#if !defined(SIMU)
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
+6
View File
@@ -175,6 +175,12 @@ void pulsesSetModuleDeInitCb(module_deinit_cb_t cb);
void restartModule(uint8_t module);
bool restartModuleAsync(uint8_t module, uint8_t cnt_delay);
// Re-Init module
//
// Note: this can only be used from within
// module init.
void pulsesRestartModuleUnsafe(uint8_t module);
void pulsesModuleSettingsUpdate(uint8_t module);
void setupPulsesPPMTrainer();
+46
View File
@@ -0,0 +1,46 @@
/*
* 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 "pxx.h"
#include "hal/module_port.h"
bool pxxClearSPort()
{
auto sport_module = modulePortGetModuleForPort(ETX_MOD_PORT_SPORT);
if (sport_module >= 0) {
// verify S.PORT is not used for TX (otherwise fail early)
auto mod_st = modulePortGetState(sport_module);
if (mod_st && mod_st->tx.port &&
mod_st->tx.port->port == ETX_MOD_PORT_SPORT) {
return false;
}
} else {
// S.PORT soft-serial cannot be used for sending
sport_module = modulePortGetModuleForPort(ETX_MOD_PORT_SPORT_INV);
}
if (sport_module >= 0) {
auto mod_st = modulePortGetState(sport_module);
if (mod_st) modulePortDeInitRxPort(mod_st);
}
return true;
}
+4
View File
@@ -45,3 +45,7 @@
#define EXTMODULE_PXX1_SERIAL_PERIOD 4000/*us*/
#define EXTMODULE_PXX1_SERIAL_BAUDRATE 420000
// Releases S.PORT usage from
// the module driver using it.
bool pxxClearSPort();
+16 -5
View File
@@ -19,6 +19,7 @@
* GNU General Public License for more details.
*/
#include "dataconstants.h"
#include "hal/module_port.h"
#include "heartbeat_driver.h"
#include "mixer_scheduler.h"
@@ -69,14 +70,17 @@ void Pxx1Pulses<PxxTransport>::addExtraFlags(uint8_t module)
extraFlags |= (g_model.moduleData[module].pxx.receiverTelemetryOff << 1);
extraFlags |= (g_model.moduleData[module].pxx.receiverHigherChannels << 2);
if (isModuleR9MNonAccess(module)) {
extraFlags |= (min<uint8_t>(g_model.moduleData[module].pxx.power, isModuleR9M_FCC_VARIANT(module) ? (uint8_t)R9M_FCC_POWER_MAX : (uint8_t)R9M_LBT_POWER_MAX) << 3);
if (isModuleR9M_EUPLUS(module))
extraFlags |= (1 << 6);
extraFlags |= (min<uint8_t>(g_model.moduleData[module].pxx.power,
isModuleR9M_FCC_VARIANT(module)
? (uint8_t)R9M_FCC_POWER_MAX
: (uint8_t)R9M_LBT_POWER_MAX)
<< 3);
if (isModuleR9M_EUPLUS(module)) extraFlags |= (1 << 6);
}
#if defined(HARDWARE_EXTERNAL_MODULE) && defined(HARDWARE_INTERNAL_MODULE)
// Disable S.PORT if internal module is active
if (module == EXTERNAL_MODULE && isSportLineUsedByInternalModule()) {
// Disable S.PORT if port is not used (might be used by the internal module)
if (module == EXTERNAL_MODULE && !modulePortIsPortUsedByModule(module, ETX_MOD_PORT_SPORT)) {
extraFlags |= (1 << 5);
}
#endif
@@ -284,6 +288,8 @@ static void* pxx1Init(uint8_t module)
if (module == INTERNAL_MODULE) {
if (!pxxClearSPort()) return nullptr;
txCfg.baudrate = _pxx1_internal_baudrate;
mod_st = modulePortInitSerial(module, ETX_MOD_PORT_UART, &txCfg, false);
@@ -361,7 +367,12 @@ static void* pxx1Init(uint8_t module)
static void pxx1DeInit(void* ctx)
{
auto mod_st = (etx_module_state_t*)ctx;
auto module = modulePortGetModule(mod_st);
modulePortDeInit(mod_st);
if (module == INTERNAL_MODULE) {
pulsesRestartModuleUnsafe(EXTERNAL_MODULE);
}
}
static void pxx1SendPulses(void* ctx, uint8_t* buffer, int16_t* channels, uint8_t nChannels)
+3 -2
View File
@@ -294,7 +294,7 @@ static void serialSetupPort(int mode, etx_serial_init& params)
case UART_MODE_TELEMETRY_MIRROR:
// TODO: query telemetry baudrate / add setting for module
#if defined(CROSSFIRE)
if (modelTelemetryProtocol() == PROTOCOL_TELEMETRY_CROSSFIRE) {
if (isModuleCrossfire(EXTERNAL_MODULE) || isModuleCrossfire(INTERNAL_MODULE)) {
params.baudrate = CROSSFIRE_TELEM_MIRROR_BAUDRATE;
break;
}
@@ -303,7 +303,8 @@ static void serialSetupPort(int mode, etx_serial_init& params)
break;
case UART_MODE_TELEMETRY:
if (modelTelemetryProtocol() == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
if (isModulePPM(EXTERNAL_MODULE) &&
g_model.telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
params.baudrate = FRSKY_D_BAUDRATE;
params.direction = ETX_Dir_RX;
}
@@ -212,6 +212,7 @@ if(PXX1)
add_definitions(-DPXX -DPXX1)
set(PULSES_SRC
${PULSES_SRC}
pxx.cpp
pxx1.cpp
)
endif()
@@ -226,7 +226,6 @@ static void _on_rx_fifo(uint8_t data)
static void* stm32_serial_init(void* hw_def, const etx_serial_init* params)
{
// TODO: check if port is already in use
auto sp = (const stm32_serial_port*)hw_def;
if (!sp) return nullptr;
@@ -234,8 +233,8 @@ static void* stm32_serial_init(void* hw_def, const etx_serial_init* params)
auto st = stm32_serial_find_state(usart);
if (!st || st->sp) return nullptr;
stm32_usart_init(usart, params);
st->sp = sp; // TODO: only iff init() is sucessful
if (!stm32_usart_init(usart, params)) return nullptr;
st->sp = sp;
if (params->direction & ETX_Dir_TX) {
// prepare for send_byte()
@@ -21,6 +21,7 @@
#include "stm32_softserial_driver.h"
#include "stm32_exti_driver.h"
#include "stm32_timer.h"
#include <string.h>
@@ -67,9 +68,13 @@ static inline void _rx_fifo_clear()
rxRidx = 0;
}
static void _softserial_init_rx(const stm32_softserial_rx_port* port,
static bool _softserial_init_rx(const stm32_softserial_rx_port* port,
const etx_serial_init* params)
{
// Test if pin is in reset state
uint32_t mode = LL_GPIO_GetPinMode(port->GPIOx, port->GPIO_Pin);
if (mode != LL_GPIO_MODE_INPUT) return false;
rxBitCount = 0;
rxBuffer = port->buffer.buffer;
rxBufLen = port->buffer.length;
@@ -80,11 +85,11 @@ static void _softserial_init_rx(const stm32_softserial_rx_port* port,
LL_TIM_StructInit(&timInit);
uint32_t freq = params->baudrate * 16;
if (!freq) return;
if (!freq) return false;
timInit.Prescaler = __LL_TIM_CALC_PSC(port->TIM_Freq, freq);
// TODO: enable_tim_clock(port->TIMx);
stm32_timer_enable_clock(port->TIMx);
LL_TIM_Init(port->TIMx, &timInit);
LL_TIM_ClearFlag_UPDATE(port->TIMx);
@@ -119,6 +124,8 @@ static void _softserial_init_rx(const stm32_softserial_rx_port* port,
// Configure EXTI for raising edge (start bit; assuming inverted serial)
_softserialPort = port;
stm32_exti_enable(port->EXTI_Line, LL_EXTI_TRIGGER_RISING, _softserial_exti);
return true;
}
static void _softserial_deinit_gpio(const stm32_softserial_rx_port* port)
@@ -142,7 +149,7 @@ static void _softserial_deinit_rx(const stm32_softserial_rx_port* port)
static void* stm32_softserial_rx_init(void* hw_def, const etx_serial_init* params)
{
auto port = (const stm32_softserial_rx_port*)hw_def;
_softserial_init_rx(port, params);
if (!_softserial_init_rx(port, params)) return nullptr;
return hw_def;
}
@@ -221,8 +221,17 @@ void stm32_usart_deinit_rx_dma(const stm32_usart_t* usart)
// - asymmetric bitrates for half-duplex (GHOST)
// - ??? ability to switch RX DMA OFF ??? (-> X12S)
//
void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params)
bool stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params)
{
// Test if the GPIO pins are in reset state
uint32_t pins = usart->GPIO_Pin;
while(pins != 0) {
uint32_t pin = 1 << POSITION_VAL(pins);
uint32_t mode = LL_GPIO_GetPinMode(usart->GPIOx, pin);
if (mode != LL_GPIO_MODE_INPUT) return false;
pins ^= pin;
}
enable_usart_clock(usart->USARTx);
LL_USART_DeInit(usart->USARTx);
@@ -258,8 +267,8 @@ void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params)
break;
default:
// TODO: return some error
return;
stm32_usart_deinit(usart);
return false;
}
usartInit.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
@@ -302,6 +311,8 @@ void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params)
LL_USART_IsEnabledIT_RXNE(usart->USARTx)) {
_enable_usart_irq(usart);
}
return true;
}
void stm32_usart_deinit(const stm32_usart_t* usart)
@@ -54,7 +54,7 @@ struct stm32_usart_t {
uint8_t txDMA_IRQ_Prio;
};
void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params);
bool stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params);
void stm32_usart_init_rx_dma(const stm32_usart_t* usart, const void* buffer, uint32_t length);
void stm32_usart_enable_tx_irq(const stm32_usart_t* usart);
void stm32_usart_set_idle_irq(const stm32_usart_t* usart, uint32_t enabled);
+30 -5
View File
@@ -23,6 +23,7 @@
#include "hal/serial_driver.h"
#include "hal/module_port.h"
#include "dataconstants.h"
#include "debug.h"
void intmoduleStop() {}
void intmoduleFifoError() {}
@@ -60,8 +61,32 @@ void stop_trainer_module_sbus() {}
void init_intmodule_heartbeat() {}
void stop_intmodule_heartbeat() {}
static void* init(void*, const etx_serial_init*) { return (void*)1; }
static void deinit(void*) {}
static bool _sport_used = false;
static void* init(void* ctx, const etx_serial_init*)
{
if (ctx == nullptr) {
return (void*)1;
}
if (ctx == (void*)&_sport_used) {
if (_sport_used) {
return nullptr;
}
_sport_used = true;
return &_sport_used;
}
return nullptr;
}
static void deinit(void* ctx)
{
if (ctx != (void*)&_sport_used) return;
_sport_used = false;
}
static void sendByte(void*, uint8_t) {}
static void sendBuffer(void*, const uint8_t*, uint32_t) {}
static void waitForTxCompleted(void*) {}
@@ -127,7 +152,7 @@ const etx_module_port_t _internal_ports[] = {
.type = ETX_MOD_TYPE_SERIAL,
.dir_flags = ETX_MOD_DIR_TX | ETX_MOD_DIR_RX,
.drv = { .serial = &_fakeSerialDriver },
.hw_def = nullptr,
.hw_def = &_sport_used,
},
#endif
};
@@ -170,7 +195,7 @@ const etx_module_port_t _external_ports[] = {
.drv = { .timer = &_fakeTimerDriver },
.hw_def = nullptr,
},
// TX inverted DMA pulse train on S.PORT
// TX inverted DMA pulse train on PPM
{
.port = ETX_MOD_PORT_SOFT_INV,
.type = ETX_MOD_TYPE_SERIAL,
@@ -184,7 +209,7 @@ const etx_module_port_t _external_ports[] = {
.type = ETX_MOD_TYPE_SERIAL,
.dir_flags = ETX_MOD_DIR_TX | ETX_MOD_DIR_RX,
.drv = { .serial = &_fakeSerialDriver },
.hw_def = nullptr,
.hw_def = &_sport_used,
},
#if defined(TELEMETRY_TIMER)
// RX soft-serial sampled bit-by-bit via timer IRQ on S.PORT
+19 -7
View File
@@ -19,6 +19,7 @@
* GNU General Public License for more details.
*/
#include "opentx.h"
#include "hal/module_port.h"
#include "telemetry.h"
#include "io/multi_protolist.h"
@@ -83,6 +84,11 @@ MultiModuleStatus &getMultiModuleStatus(uint8_t module)
return multiModuleStatus[module];
}
static uint8_t _getMultiStatusModuleIdx(const MultiModuleStatus* p)
{
return p - multiModuleStatus;
}
uint8_t getMultiBindStatus(uint8_t module)
{
return multiBindStatus[module];
@@ -116,6 +122,11 @@ MultiModuleStatus& getMultiModuleStatus(uint8_t)
return multiModuleStatus;
}
static uint8_t _getMultiStatusModuleIdx(const MultiModuleStatus*)
{
return EXTERNAL_MODULE;
}
uint8_t getMultiBindStatus(uint8_t)
{
return multiBindStatus;
@@ -497,14 +508,11 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module)
void MultiModuleStatus::getStatusString(char * statusText) const
{
if (!isValid()) {
#if defined(PCBFRSKY)
#if !defined(INTERNAL_MODULE_MULTI)
if (isSportLineUsedByInternalModule())
if (!modulePortIsPortUsedByModule(getModuleIndex(), ETX_MOD_PORT_SPORT)) {
strcpy(statusText, STR_DISABLE_INTERNAL);
else
#endif
#endif
strcpy(statusText, STR_MODULE_NO_TELEMETRY);
} else {
strcpy(statusText, STR_MODULE_NO_TELEMETRY);
}
return;
}
if (!protocolValid()) {
@@ -556,6 +564,10 @@ void MultiModuleStatus::getStatusString(char * statusText) const
}
}
uint8_t MultiModuleStatus::getModuleIndex() const {
return _getMultiStatusModuleIdx(this);
}
static void processMultiTelemetryByte(const uint8_t data, uint8_t module)
{
uint8_t * rxBuffer = getTelemetryRxBuffer(module);
+2
View File
@@ -120,6 +120,8 @@ struct MultiModuleStatus {
void getStatusString(char * statusText) const;
uint8_t getModuleIndex() const;
inline bool isValid() const { return (bool)(get_tmr10ms() - lastUpdate < 200); }
inline bool isBufferFull() const { return (bool) (flags & 0x80); }
inline bool supportsDisableMapping() const { return (bool) (flags & 0x40); }
-53
View File
@@ -68,8 +68,6 @@ uint8_t telemetryState = TELEMETRY_INIT;
TelemetryData telemetryData;
uint8_t telemetryProtocol = 255;
#if defined(INTERNAL_MODULE_SERIAL_TELEMETRY)
static uint8_t intTelemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE];
static uint8_t intTelemetryRxBufferCount;
@@ -418,60 +416,9 @@ void telemetryReset()
}
telemetryStreaming = 0; // reset counter only if valid telemetry packets are being detected
telemetryState = TELEMETRY_INIT;
}
// we don't reset the telemetry here as we would also reset the consumption after model load
void telemetryInit(uint8_t protocol)
{
telemetryProtocol = protocol;
// if (protocol == PROTOCOL_TELEMETRY_FRSKY_D) {
// telemetryPortInit(FRSKY_D_BAUDRATE, TELEMETRY_SERIAL_DEFAULT);
// }
// #if defined(MULTIMODULE)
// else if (protocol == PROTOCOL_TELEMETRY_MULTIMODULE) {
// // The DIY Multi module always speaks 100000 baud regardless of the
// // telemetry protocol in use
// telemetryPortInit(MULTIMODULE_BAUDRATE, TELEMETRY_SERIAL_8E2);
// #if defined(LUA)
// outputTelemetryBuffer.reset();
// #endif
// telemetryPortSetDirectionInput();
// } else if (protocol == PROTOCOL_TELEMETRY_SPEKTRUM) {
// // Spektrum's own small race RX (SPM4648) uses 125000 8N1, use the same
// // since there is no real standard
// telemetryPortInit(125000, TELEMETRY_SERIAL_DEFAULT);
// }
// #endif
// #if defined(GHOST)
// else if (protocol == PROTOCOL_TELEMETRY_GHOST) {
// telemetryPortInit(GHOST_BAUDRATE, TELEMETRY_SERIAL_DEFAULT);
// #if defined(LUA)
// outputTelemetryBuffer.reset();
// #endif
// telemetryPortSetDirectionOutput();
// }
// #endif
// #if defined(AUX_SERIAL)
// else if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
// telemetryPortInit(0, TELEMETRY_SERIAL_DEFAULT);
// }
// #endif
// else if (protocol == PROTOCOL_TELEMETRY_DSMP) {
// // soft serial
// telemetryPortInvertedInit(115200);
// } else {
// telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_WITHOUT_DMA);
// #if defined(LUA)
// outputTelemetryBuffer.reset();
// #endif
// }
}
#if defined(LOG_TELEMETRY) && !defined(SIMU)
extern FIL g_telemetryFile;
void logTelemetryWriteStart()
-54
View File
@@ -133,60 +133,6 @@ typedef struct {
rxStatStruct *getRxStatLabels();
// TODO: this should handle only the external S.PORT line
// - and go away in the end: one proto per module, not global!
//
inline uint8_t modelTelemetryProtocol()
{
#if defined(HARDWARE_EXTERNAL_MODULE)
bool sportUsed = isSportLineUsedByInternalModule();
#if defined(CROSSFIRE)
if (isModuleCrossfire(EXTERNAL_MODULE)) {
return PROTOCOL_TELEMETRY_CROSSFIRE;
}
#endif
#if defined(GHOST)
if (isModuleGhost(EXTERNAL_MODULE)) {
return PROTOCOL_TELEMETRY_GHOST;
}
#endif
// TODO: PPM driver should support setting up a telemetry parser callback
if (!sportUsed && isModulePPM(EXTERNAL_MODULE)) {
return g_model.telemetryProtocol;
}
#if defined(MULTIMODULE)
if (!sportUsed && isModuleMultimodule(EXTERNAL_MODULE)) {
return PROTOCOL_TELEMETRY_MULTIMODULE;
}
#endif
#if defined(AFHDS3)
if (isModuleAFHDS3(EXTERNAL_MODULE)) {
return PROTOCOL_TELEMETRY_AFHDS3;
}
#endif
if (isModuleDSMP(EXTERNAL_MODULE)) {
return PROTOCOL_TELEMETRY_DSMP;
}
#endif // HARDWARE_EXTERNAL_MODULE
// TODO: Check if that is really necessary...
#if defined(AFHDS2) && defined(HARDWARE_INTERNAL_MODULE)
if (isModuleAFHDS2A(INTERNAL_MODULE)) {
return PROTOCOL_TELEMETRY_FLYSKY_NV14;
}
#endif
// default choice
return PROTOCOL_TELEMETRY_FRSKY_SPORT;
}
#include "telemetry_sensors.h"
#if defined(LOG_TELEMETRY) && !defined(SIMU)
+189
View File
@@ -20,7 +20,11 @@
*/
#include "gtests.h"
#include "hal/module_driver.h"
#include "hal/module_port.h"
#include "pulses/modules_constants.h"
#include "pulses/pulses.h"
#include "translations.h"
TEST(ports, softserialFallback)
{
@@ -48,3 +52,188 @@ TEST(ports, softserialFallback)
modulePortDeInit(mod_st);
}
}
#if defined(HARDWARE_EXTERNAL_MODULE)
TEST(ports, isPortUsed)
{
modulePortInit();
const etx_serial_init serialCfg = {
.baudrate = 57600,
.encoding = ETX_Encoding_8N1,
.direction = ETX_Dir_TX_RX,
.polarity = ETX_Pol_Normal,
};
auto mod_st = modulePortInitSerial(EXTERNAL_MODULE, ETX_MOD_PORT_SPORT,
&serialCfg, false);
EXPECT_TRUE(mod_st != nullptr);
EXPECT_TRUE(mod_st && mod_st->rx.port != nullptr);
auto module = modulePortGetModuleForPort(ETX_MOD_PORT_SPORT);
EXPECT_EQ(EXTERNAL_MODULE, module);
if (mod_st) modulePortDeInit(mod_st);
EXPECT_FALSE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
}
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(HARDWARE_EXTERNAL_MODULE)
#include "pulses/pxx1.h"
static void _setModuleDrv(uint8_t module, const etx_proto_driver_t* drv, void* ctx)
{
auto mod_drv = pulsesGetModuleDriver(module);
mod_drv->drv = drv;
mod_drv->ctx = ctx;
}
static void _deinitModuleDrv(uint8_t module)
{
auto mod_drv = pulsesGetModuleDriver(module);
auto drv = mod_drv->drv;
auto ctx = mod_drv->ctx;
drv->deinit(ctx);
memset(mod_drv, 0, sizeof(module_pulse_driver));
}
static void _sendPulses(uint8_t module, uint8_t* buffer)
{
auto mod_drv = pulsesGetModuleDriver(module);
auto drv = mod_drv->drv;
auto ctx = mod_drv->ctx;
int16_t* channels = &channelOutputs[0];
drv->sendPulses(ctx, buffer, channels, 16);
}
TEST(ports, deactivateRX_pxx1)
{
modulePortInit();
g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_R9M_PXX1;
void* ext_ctx = Pxx1Driver.init(EXTERNAL_MODULE);
EXPECT_TRUE(ext_ctx != nullptr);
EXPECT_TRUE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
if (!ext_ctx) return;
_setModuleDrv(EXTERNAL_MODULE, &Pxx1Driver, ext_ctx);
void* int_ctx = Pxx1Driver.init(INTERNAL_MODULE);
EXPECT_TRUE(int_ctx != nullptr);
EXPECT_EQ(INTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
if (!int_ctx) return;
_setModuleDrv(INTERNAL_MODULE, &Pxx1Driver, int_ctx);
_deinitModuleDrv(INTERNAL_MODULE);
EXPECT_EQ(EXTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
_deinitModuleDrv(EXTERNAL_MODULE);
EXPECT_FALSE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
}
#include "pulses/multi.h"
#include "telemetry/multi.h"
TEST(ports, deactivateRX_multi)
{
modulePortInit();
g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_MULTIMODULE;
void* ext_ctx = MultiDriver.init(EXTERNAL_MODULE);
EXPECT_TRUE(ext_ctx != nullptr);
EXPECT_TRUE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
if (!ext_ctx) return;
_setModuleDrv(EXTERNAL_MODULE, &MultiDriver, ext_ctx);
uint8_t buffer[64];
_sendPulses(EXTERNAL_MODULE, buffer);
EXPECT_FALSE(buffer[0x1A] & 2);
auto& mpm_status = getMultiModuleStatus(EXTERNAL_MODULE);
mpm_status.invalidate();
mpm_status.getStatusString((char*)buffer);
EXPECT_STREQ(STR_MODULE_NO_TELEMETRY, (char*)buffer);
void* int_ctx = Pxx1Driver.init(INTERNAL_MODULE);
EXPECT_TRUE(int_ctx != nullptr);
EXPECT_EQ(INTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
if (!int_ctx) return;
_setModuleDrv(INTERNAL_MODULE, &Pxx1Driver, int_ctx);
_sendPulses(EXTERNAL_MODULE, buffer);
EXPECT_TRUE(buffer[0x1A] & 2);
mpm_status.getStatusString((char*)buffer);
EXPECT_STREQ(STR_DISABLE_INTERNAL, (char*)buffer);
_deinitModuleDrv(INTERNAL_MODULE);
EXPECT_EQ(EXTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
_sendPulses(EXTERNAL_MODULE, buffer);
EXPECT_FALSE(buffer[0x1A] & 2);
_deinitModuleDrv(EXTERNAL_MODULE);
EXPECT_FALSE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
}
TEST(ports, boot_pxx1_multi)
{
modulePortInit();
g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_MULTIMODULE;
// Init PXX1 internal module first
void* int_ctx = Pxx1Driver.init(INTERNAL_MODULE);
EXPECT_TRUE(int_ctx != nullptr);
if (!int_ctx) return;
_setModuleDrv(INTERNAL_MODULE, &Pxx1Driver, int_ctx);
EXPECT_TRUE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
EXPECT_EQ(INTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
// Init MPM external module second
void* ext_ctx = MultiDriver.init(EXTERNAL_MODULE);
EXPECT_TRUE(ext_ctx != nullptr);
if (!ext_ctx) return;
_setModuleDrv(EXTERNAL_MODULE, &MultiDriver, ext_ctx);
// Verify internal module still owns S.PORT
EXPECT_EQ(INTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
EXPECT_FALSE(modulePortIsPortUsedByModule(EXTERNAL_MODULE, ETX_MOD_PORT_SPORT));
// Verify MPM sends "disable telemetry" bit
uint8_t buffer[64];
_sendPulses(EXTERNAL_MODULE, buffer);
EXPECT_TRUE(buffer[0x1A] & 2);
// Verify MPM status
auto& mpm_status = getMultiModuleStatus(EXTERNAL_MODULE);
mpm_status.invalidate();
mpm_status.getStatusString((char*)buffer);
EXPECT_STREQ(STR_DISABLE_INTERNAL, (char*)buffer);
// Disable internal module
_deinitModuleDrv(INTERNAL_MODULE);
// Verify external module now owns S.PORT
EXPECT_EQ(EXTERNAL_MODULE, modulePortGetModuleForPort(ETX_MOD_PORT_SPORT));
// Verify MPM does not send "disable telemetry" bit
_sendPulses(EXTERNAL_MODULE, buffer);
EXPECT_FALSE(buffer[0x1A] & 2);
// Verify MPM status
mpm_status.getStatusString((char*)buffer);
EXPECT_STREQ(STR_MODULE_NO_TELEMETRY, (char*)buffer);
// disable MPM
_deinitModuleDrv(EXTERNAL_MODULE);
EXPECT_FALSE(modulePortIsPortUsed(ETX_MOD_PORT_SPORT));
}
#endif