chore: New module/serial API (#3055)

* WiP: new module interface

* WiP: softserial timer DMA

* WiP: setup() and send() in one step

and remove methods specific to internal or external module

* fixes and extra port config

* horus targets

* module ports have moved

* T8 support (only internal module)

* fix nv14

* stupid GCC....

* disable BT

* remove nv14 telem driver

* remove old aux serial driver

* Move module buffers out of pulses.h

* Soft serial fixes and PXX1 support

* Fixed PPM module output

* Fixed CLI

* compilation fixes

* Ported bluetooth and flysky gimbal to new serial driver

* Re-enable soft-serial RX

* fixes and cleanup

* nv14 fixes

* Fix flysky gimbals

* Ghost module

* 16 bytes of RAM

* Remove getByte from module API

* Ghost cleanup

* fix: _half_duplex_input() must be called after usart init

* WiP

* more cleanup

* Remove board specific settings from PXX1 / PXX2 drivers

* A bit of PXX2 header cleanup

* Add support for OVER8 and ONEBIT

* Add some support for inverters (NV14 / EL18)

* Support NV14 power fixes in generic board

* Fix polarity handling

* Fix RX DMA

* Fix mixer not running

* Add soft-serial polarity control

* Quick fix for telemetry polling while module port is changed

* Fix bootloader DEBUG

* Fix MPM telemetry

* Fix pulse start

* DSM2 soft-serial fallback

* DSMP async module restart

* Fix CRSF LUA upstream

* Remove global variable telemetryProtocol

* Use HAL/LL constants

* Fix various issue with AFHDS3 and NV14/EL18 internal module

* Fixed S.PORT unit tests

* fix: update widx after writing at current index

* fix: init error condition

* Fix: possible infinite loop in _find_port()

* Add support for bidir S.PORT init

* Add support for "getLastByte" in HW serial driver

* PXX1: Add support for S.PORT based on IDLE callback

* Fix rebase error

* Fix softserial _rx_fifo_push()

* Add softserial support for waitForTxCompleted()

* Fix MPM flashing (internal / external)

* Fixed external MPM

* Activate RX DMA on internal module

Seems to work with serial passthrough without issues, at least on the L3R PRO.

* Fix softserial DMA on stdlcd F4 targets

* Add softserial support for 32bit timers (mostly TIM2)

* More precise soft-serial

* Fix MPM update using inverters & HW uart

* Raise S.PORT DMA/USART IRQ prio to achieve faster switching to input

* Remove useless delays

* Fix flashing external ELRS module

* Added a retry mechanism for FrSky S.PORT update

* Remove useless enableRx()

* External FrSky modules are all flashed via S.PORT

* Remove power management unit update

This was only used on the first batch of X-lite.
This commit is contained in:
Raphael Coeffic
2023-02-09 19:44:32 +10:00
committed by GitHub
parent d80adc6c4d
commit 72193eda82
189 changed files with 7960 additions and 8364 deletions
+98 -155
View File
@@ -25,7 +25,7 @@
#include "pulses/flysky.h"
#include "mixer_scheduler.h"
#include "io/multi_protolist.h"
#include "aux_serial_driver.h"
#include "hal/module_port.h"
#if defined(LIBOPENUI)
#include "libopenui.h"
@@ -57,12 +57,8 @@
#include "flysky_ibus.h"
#endif
#if defined(INTMODULE_USART)
#include "intmodule_serial_driver.h"
#endif
uint8_t telemetryStreaming = 0;
uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1)
uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE];
uint8_t telemetryRxBufferCount = 0;
uint8_t telemetryState = TELEMETRY_INIT;
@@ -94,27 +90,30 @@ uint8_t &getTelemetryRxBufferCount(uint8_t moduleIdx)
return telemetryRxBufferCount;
}
static int (*_telemetryGetByte)(void*, uint8_t*) = nullptr;
static void* _telemetryGetByteCtx = nullptr;
// TODO: move to module port driver
//
// static int (*_telemetryGetByte)(void*, uint8_t*) = nullptr;
// static void* _telemetryGetByteCtx = nullptr;
void telemetrySetGetByte(void* ctx, int (*fct)(void*, uint8_t*))
{
_telemetryGetByte = nullptr;
_telemetryGetByteCtx = ctx;
_telemetryGetByte = fct;
}
// void telemetrySetGetByte(void* ctx, int (*fct)(void*, uint8_t*))
// {
// _telemetryGetByte = nullptr;
// _telemetryGetByteCtx = ctx;
// _telemetryGetByte = fct;
// }
static bool telemetryGetByte(uint8_t* data)
{
auto _getByte = _telemetryGetByte;
auto _ctx = _telemetryGetByteCtx;
// static bool telemetryGetByte(uint8_t* data)
// {
// auto _getByte = _telemetryGetByte;
// auto _ctx = _telemetryGetByteCtx;
if (_getByte) {
return _getByte(_ctx, data);
}
// if (_getByte) {
// return _getByte(_ctx, data);
// }
return sportGetByte(data);
}
// // return sportGetByte(data);
// return false;
// }
static void (*telemetryMirrorSendByte)(void*, uint8_t) = nullptr;
static void* telemetryMirrorSendByteCtx = nullptr;
@@ -143,11 +142,10 @@ static StaticTimer_t telemetryTimerBuffer;
static void telemetryTimerCb(TimerHandle_t xTimer)
{
(void)xTimer;
if (!s_pulses_paused) {
DEBUG_TIMER_START(debugTimerTelemetryWakeup);
telemetryWakeup();
DEBUG_TIMER_STOP(debugTimerTelemetryWakeup);
}
DEBUG_TIMER_START(debugTimerTelemetryWakeup);
telemetryWakeup();
DEBUG_TIMER_STOP(debugTimerTelemetryWakeup);
}
void telemetryStart()
@@ -175,122 +173,61 @@ void telemetryStop()
}
#endif
void processTelemetryData(uint8_t data)
{
// TODO: move these to new interface
#if defined(GHOST)
if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) {
processGhostTelemetryData(data);
return;
}
#endif
if (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM ||
telemetryProtocol == PROTOCOL_TELEMETRY_DSMP) {
processSpektrumTelemetryData(EXTERNAL_MODULE, data, telemetryRxBuffer,
telemetryRxBufferCount);
return;
}
// TODO: move these to new interface
#if defined(MULTIMODULE)
if (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE) {
processMultiTelemetryData(data, EXTERNAL_MODULE);
return;
}
#endif
#if defined(PXX1)
if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT ||
telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_D ||
telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
processFrskyTelemetryData(data);
}
#endif
}
inline bool isBadAntennaDetected()
{
if (!isRasValueValid())
return false;
if (telemetryData.swrInternal.isFresh() && telemetryData.swrInternal.value() > FRSKY_BAD_ANTENNA_THRESHOLD)
if (telemetryData.swrInternal.isFresh() &&
telemetryData.swrInternal.value() > FRSKY_BAD_ANTENNA_THRESHOLD)
return true;
if (telemetryData.swrExternal.isFresh() && telemetryData.swrExternal.value() > FRSKY_BAD_ANTENNA_THRESHOLD)
if (telemetryData.swrExternal.isFresh() &&
telemetryData.swrExternal.value() > FRSKY_BAD_ANTENNA_THRESHOLD)
return true;
return false;
}
static inline bool pollTelemetry(uint8_t module, const etx_module_driver_t* drv, void* ctx)
static inline void pollTelemetry(uint8_t module, const etx_proto_driver_t* drv, void* ctx)
{
if (!drv || !drv->getByte || !drv->processData) return false;
if (!drv || !drv->processData) return;
auto mod_st = (etx_module_state_t*)ctx;
auto serial_drv = modulePortGetSerialDrv(mod_st->rx);
auto serial_ctx = modulePortGetCtx(mod_st->rx);
if (!serial_drv || !serial_ctx || !serial_drv->getByte)
return;
uint8_t* rxBuffer = getTelemetryRxBuffer(module);
uint8_t& rxBufferCount = getTelemetryRxBufferCount(module);
uint8_t data;
if (drv->getByte(ctx, &data) > 0) {
if (serial_drv->getByte(serial_ctx, &data) > 0) {
LOG_TELEMETRY_WRITE_START();
do {
telemetryMirrorSend(data);
drv->processData(ctx, data, rxBuffer, &rxBufferCount);
LOG_TELEMETRY_WRITE_BYTE(data);
} while (drv->getByte(ctx, &data) > 0);
} while (serial_drv->getByte(serial_ctx, &data) > 0);
}
return true;
}
static inline void pollExtTelemetryLegacy()
{
uint8_t data;
if (telemetryGetByte(&data)) {
LOG_TELEMETRY_WRITE_START();
do {
telemetryMirrorSend(data);
processTelemetryData(data);
LOG_TELEMETRY_WRITE_BYTE(data);
} while (telemetryGetByte(&data));
}
}
// This can only be changed when the mixer is not
// running as the priority of the timer task is
// lower.
volatile uint8_t _telemetryIsPolling = false;
// TODO: this needs to be rewritten completely
// - telemetry polling needs to happen for each enabled module
void telemetryWakeup()
{
#if defined(HARDWARE_INTERNAL_MODULE)
auto int_drv = getIntModuleDriver();
if (int_drv) pollTelemetry(INTERNAL_MODULE, int_drv, getIntModuleCtx());
#endif
bool disable_legacy_polling = false;
#if defined(HARDWARE_EXTERNAL_MODULE)
auto ext_drv = getExtModuleDriver();
if (ext_drv) {
if (pollTelemetry(EXTERNAL_MODULE, ext_drv, getExtModuleCtx())) {
// skip legacy telemetry polling in case external module
// driver defines telemetry methods (getByte & processData)
disable_legacy_polling = true;
}
}
#endif
if (!disable_legacy_polling) {
// TODO: needs to be moved to protocol/module init
// as-is, it implies only ONE telemetry protocol
// enabled at the same time
uint8_t requiredTelemetryProtocol = modelTelemetryProtocol();
if (telemetryProtocol != requiredTelemetryProtocol) {
telemetryInit(requiredTelemetryProtocol);
}
// Poll external / S.PORT telemetry
// TODO: how to switch this OFF ???
pollExtTelemetryLegacy();
_telemetryIsPolling = true;
for (uint8_t i = 0; i < MAX_MODULES; i++) {
auto mod = pulsesGetModuleDriver(i);
if (!mod) continue;
pollTelemetry(i, mod->drv, mod->ctx);
}
_telemetryIsPolling = false;
for (int i=0; i<MAX_TELEMETRY_SENSORS; i++) {
const TelemetrySensor & sensor = g_model.telemetrySensors[i];
@@ -352,14 +289,20 @@ void telemetryWakeup()
if (TELEMETRY_STREAMING()) {
if (telemetryState == TELEMETRY_KO) {
AUDIO_TELEMETRY_BACK();
#if defined(CROSSFIRE)
// TODO: move to crossfire code
#if defined(HARDWARE_EXTERNAL_MODULE)
if (isModuleCrossfire(EXTERNAL_MODULE)) {
moduleState[EXTERNAL_MODULE].counter = CRSF_FRAME_MODELID;
}
#endif
#if defined(HARDWARE_INTERNAL_MODULE)
if (isModuleCrossfire(INTERNAL_MODULE)) {
moduleState[INTERNAL_MODULE].counter = CRSF_FRAME_MODELID;
}
#endif
#endif
}
telemetryState = TELEMETRY_OK;
@@ -419,49 +362,49 @@ 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 (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(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(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)