From 02660c763ae1388e02fd7606b795269e522d8e10 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 19 Oct 2019 23:08:51 +0200 Subject: [PATCH 01/37] mixer scheduler --- radio/src/CMakeLists.txt | 1 + radio/src/gui/gui_common.h | 3 +- radio/src/mixer_scheduler.cpp | 79 +++++++++++ radio/src/mixer_scheduler.h | 84 +++++++++++ radio/src/opentx.h | 1 - radio/src/pulses/dsm2.cpp | 6 +- radio/src/pulses/multi.cpp | 2 - radio/src/pulses/pulses.cpp | 109 ++++++++++---- radio/src/pulses/pulses.h | 9 +- radio/src/pulses/pxx.h | 12 +- radio/src/pulses/sbus.cpp | 2 - radio/src/rtos.h | 32 ++++- .../common/arm/stm32/heartbeat_driver.cpp | 3 + .../arm/stm32/intmodule_serial_driver.cpp | 37 ----- .../arm/stm32/mixer_scheduler_driver.cpp | 81 +++++++++++ radio/src/targets/horus/CMakeLists.txt | 1 + radio/src/targets/horus/board.cpp | 1 + radio/src/targets/horus/board.h | 5 +- radio/src/targets/horus/extmodule_driver.cpp | 44 ++++-- radio/src/targets/horus/hal.h | 7 + radio/src/targets/taranis/CMakeLists.txt | 1 + radio/src/targets/taranis/board.cpp | 3 +- radio/src/targets/taranis/board.h | 2 +- .../src/targets/taranis/extmodule_driver.cpp | 39 +++-- radio/src/targets/taranis/hal.h | 7 + radio/src/tasks.cpp | 89 ++++++------ radio/src/telemetry/crossfire.cpp | 20 +++ radio/src/telemetry/crossfire.h | 6 +- radio/src/telemetry/multi.cpp | 133 ++---------------- radio/src/telemetry/multi.h | 22 --- radio/src/telemetry/telemetry.cpp | 86 +++++++++++ radio/src/telemetry/telemetry.h | 31 ++++ 32 files changed, 644 insertions(+), 314 deletions(-) create mode 100644 radio/src/mixer_scheduler.cpp create mode 100644 radio/src/mixer_scheduler.h create mode 100644 radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 47a1fed2a..39ea7e52e 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -378,6 +378,7 @@ set(SRC strhelpers.cpp switches.cpp mixer.cpp + mixer_scheduler.cpp stamp.cpp timers.cpp trainer.cpp diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index dd473eee8..3894bf633 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -185,6 +185,7 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) } #if defined(MULTIMODULE) + inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx) { if (!isModuleMultimodule(moduleIdx)) @@ -276,7 +277,7 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx) #define MULTIMODULE_MODULE_ROWS(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) && !IS_RX_MULTI(moduleIdx)) ? (uint8_t) 0 : HIDDEN_ROW, (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) && !IS_RX_MULTI(moduleIdx)) ? (uint8_t) 0 : HIDDEN_ROW, MULTI_DISABLE_CHAN_MAP_ROW(moduleIdx), // AUTOBIND, DISABLE TELEM, DISABLE CN.MAP #define MULTIMODULE_TYPE_ROW(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW, -#define MULTIMODULE_STATUS_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(moduleIdx) && getMultiSyncStatus(moduleIdx).isValid()) ? TITLE_ROW : HIDDEN_ROW, +#define MULTIMODULE_STATUS_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(moduleIdx) && getModuleSyncStatus(moduleIdx).isValid()) ? TITLE_ROW : HIDDEN_ROW, #define MULTIMODULE_MODE_ROWS(moduleIdx) (g_model.moduleData[moduleIdx].multi.customProto) ? (uint8_t) 3 : MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t)2 : (uint8_t)1 #define MULTIMODULE_TYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, #define MULTIMODULE_SUBTYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW, diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp new file mode 100644 index 000000000..b29c821c8 --- /dev/null +++ b/radio/src/mixer_scheduler.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "opentx.h" +#include "mixer_scheduler.h" + +#if !defined(SIMU) + +// Global trigger flag +RTOS_FLAG_HANDLE mixerFlag; + +// Mixer schedule +struct MixerSchedule { + + // period in us + volatile uint16_t period; +}; + +static MixerSchedule mixerSchedules[NUM_MODULES]; + +uint16_t getMixerSchedulerPeriod() +{ + if (mixerSchedules[INTERNAL_MODULE].period) { + return mixerSchedules[INTERNAL_MODULE].period; + } + else if (mixerSchedules[EXTERNAL_MODULE].period) { + return mixerSchedules[EXTERNAL_MODULE].period; + } + + return MIXER_SCHEDULER_DEFAULT_PERIOD_US; +} + +void mixerSchedulerInit() +{ + RTOS_CREATE_FLAG(mixerFlag); + memset(mixerSchedules, 0, sizeof(mixerSchedules)); +} + +void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs) +{ + if ((periodUs > 0) && (periodUs < MIN_REFRESH_RATE)) { + periodUs = MIN_REFRESH_RATE; + } + else if ((periodUs > 0) && (periodUs > MAX_REFRESH_RATE)) { + periodUs = MAX_REFRESH_RATE; + } + + mixerSchedules[moduleIdx].period = periodUs; +} + +bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs) +{ + RTOS_CLEAR_FLAG(mixerFlag); + return RTOS_WAIT_FLAG(mixerFlag, timeoutMs); +} + +void mixerSchedulerISRTrigger() +{ + RTOS_ISR_SET_FLAG(mixerFlag); +} + +#endif diff --git a/radio/src/mixer_scheduler.h b/radio/src/mixer_scheduler.h new file mode 100644 index 000000000..ccded9a5e --- /dev/null +++ b/radio/src/mixer_scheduler.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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. + */ + +#ifndef _MIXER_SCHEDULER_H_ +#define _MIXER_SCHEDULER_H_ + +#define MIXER_SCHEDULER_DEFAULT_PERIOD_US 4000u // 4ms + +#define MIN_REFRESH_RATE 4000 /* us */ +#define MAX_REFRESH_RATE 25000 /* us */ + +#if !defined(SIMU) + +// Call once to initialize the mixer scheduler +void mixerSchedulerInit(); + +// Configure and start the scheduler timer +void mixerSchedulerStart(); + +// Stop the scheduler timer +void mixerSchedulerStop(); + +// Set the timer counter to 0 +void mixerSchedulerResetTimer(); + +// Set the scheduling period for a given module +void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs); + +// Wait for the scheduler timer to trigger +// returns true if timeout, false otherwise +bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs); + +// Enable the timer trigger +void mixerSchedulerEnableTrigger(); + +// Disable the timer trigger +void mixerSchedulerDisableTrigger(); + +// Fetch the current scheduling period +uint16_t getMixerSchedulerPeriod(); + +// Trigger mixer from an ISR +void mixerSchedulerISRTrigger(); + +#else + +#define mixerSchedulerInit() +#define mixerSchedulerStart() +#define mixerSchedulerStop() +#define mixerSchedulerResetTimer() +#define mixerSchedulerSetPeriod(m,p) + +static inline bool mixerSchedulerWaitForTrigger(uint8_t timeout) +{ + simuSleep(timeout); + return false; +} + +#define mixerSchedulerEnableTrigger() +#define mixerSchedulerDisableTrigger() + +#define getMixerSchedulerPeriod() (MIXER_SCHEDULER_DEFAULT_PERIOD_US) +#define mixerSchedulerISRTrigger() + +#endif + +#endif diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 52a51719b..394a0734f 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -483,7 +483,6 @@ extern uint32_t nextMixerTime[NUM_MODULES]; void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms); void evalMixes(uint8_t tick10ms); void doMixerCalculations(); -void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms); void checkTrims(); extern uint8_t currentBacklightBright; diff --git a/radio/src/pulses/dsm2.cpp b/radio/src/pulses/dsm2.cpp index 3612f60db..34a10b3d6 100644 --- a/radio/src/pulses/dsm2.cpp +++ b/radio/src/pulses/dsm2.cpp @@ -76,7 +76,6 @@ void _send_1(uint8_t v) *extmodulePulsesData.dsm2.ptr++ = v - 1; extmodulePulsesData.dsm2.index += 1; - extmodulePulsesData.dsm2.rest -= v; } void sendByteDsm2(uint8_t b) // max 10 changes 0 10 10 10 10 1 @@ -101,9 +100,9 @@ void sendByteDsm2(uint8_t b) // max 10 changes 0 10 10 10 10 1 void putDsm2Flush() { if (extmodulePulsesData.dsm2.index & 1) - *extmodulePulsesData.dsm2.ptr++ = extmodulePulsesData.dsm2.rest; + *extmodulePulsesData.dsm2.ptr++ = 60000; else - *(extmodulePulsesData.dsm2.ptr - 1) = extmodulePulsesData.dsm2.rest; + *(extmodulePulsesData.dsm2.ptr - 1) = 60000; } #endif @@ -119,7 +118,6 @@ void setupPulsesDSM2() extmodulePulsesData.dsm2.serialBitCount = 0 ; #else extmodulePulsesData.dsm2.index = 0; - extmodulePulsesData.dsm2.rest = DSM2_PERIOD * 2000; #endif extmodulePulsesData.dsm2.ptr = extmodulePulsesData.dsm2.pulses; diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index dcc7c7f9c..4f61caf72 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -209,10 +209,8 @@ void setupPulsesMultiExternalModule() extmodulePulsesData.dsm2.serialByte = 0 ; extmodulePulsesData.dsm2.serialBitCount = 0 ; #else - extmodulePulsesData.dsm2.rest = getMultiSyncStatus(EXTERNAL_MODULE).getAdjustedRefreshRate(); extmodulePulsesData.dsm2.index = 0; #endif - extmodulePulsesData.dsm2.ptr = extmodulePulsesData.dsm2.pulses; setupPulsesMulti(EXTERNAL_MODULE); diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index d6833bfe9..1681157bc 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -21,6 +21,7 @@ #include "opentx.h" #include "io/frsky_pxx2.h" #include "pulses/pxx2.h" +#include "mixer_scheduler.h" uint8_t s_pulses_paused = 0; ModuleState moduleState[NUM_MODULES]; @@ -62,7 +63,7 @@ void getModuleSyncStatusString(uint8_t moduleIdx, char * statusText) *statusText = 0; #if defined(MULTIMODULE) if (isModuleMultimodule(moduleIdx)) { - getMultiSyncStatus(moduleIdx).getRefreshString(statusText); + getModuleSyncStatus(moduleIdx).getRefreshString(statusText); } #endif #if defined(AFHDS3) @@ -225,12 +226,14 @@ void enablePulsesExternalModule(uint8_t protocol) #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: extmodulePxx1PulsesStart(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX_PULSES_PERIOD); break; #endif #if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) case PROTOCOL_CHANNELS_PXX1_SERIAL: extmodulePxx1SerialStart(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, EXTMODULE_PXX1_SERIAL_PERIOD); break; #endif @@ -238,59 +241,69 @@ void enablePulsesExternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_DSM2_LP45: case PROTOCOL_CHANNELS_DSM2_DSM2: case PROTOCOL_CHANNELS_DSM2_DSMX: - extmoduleSerialStart(DSM2_BAUDRATE, DSM2_PERIOD * 2000, false); + extmoduleSerialStart(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, DSM2_PERIOD); break; #endif #if defined(CROSSFIRE) case PROTOCOL_CHANNELS_CROSSFIRE: EXTERNAL_MODULE_ON(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, CROSSFIRE_PERIOD); break; #endif #if defined(GHOST) case PROTOCOL_CHANNELS_GHOST: EXTERNAL_MODULE_ON(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, GHOST_PERIOD); break; #endif #if defined(PXX2) && defined(EXTMODULE_USART) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: extmoduleInvertedSerialStart(PXX2_HIGHSPEED_BAUDRATE); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_PERIOD); break; case PROTOCOL_CHANNELS_PXX2_LOWSPEED: extmoduleInvertedSerialStart(PXX2_LOWSPEED_BAUDRATE); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_PERIOD); break; #endif #if defined(MULTIMODULE) case PROTOCOL_CHANNELS_MULTIMODULE: - extmoduleSerialStart(MULTIMODULE_BAUDRATE, MULTIMODULE_PERIOD * 2000, true); + extmoduleSerialStart(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD); break; #endif #if defined(SBUS) case PROTOCOL_CHANNELS_SBUS: - extmoduleSerialStart(SBUS_BAUDRATE, SBUS_PERIOD_HALF_US, false); + extmoduleSerialStart(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD); break; #endif #if defined(PPM) case PROTOCOL_CHANNELS_PPM: extmodulePpmStart(); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE)); break; #endif #if defined(AFHDS3) case PROTOCOL_CHANNELS_AFHDS3: extmodulePulsesData.afhds3.init(EXTERNAL_MODULE); - extmoduleSerialStart(AFHDS3_BAUDRATE, AFHDS3_COMMAND_TIMEOUT * 2000, false); + extmoduleSerialStart(/*AFHDS3_BAUDRATE, AFHDS3_COMMAND_TIMEOUT * 2000, false*/); + mixerSchedulerSetPeriod(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT * 1000 /* us */); break; #endif - default: + // external module stopped, set period to 50ms (necessary for USB Joystick, for instance) + mixerSchedulerSetPeriod(EXTERNAL_MODULE, 50000/*us*/); break; } } @@ -301,14 +314,12 @@ bool setupPulsesExternalModule(uint8_t protocol) #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: extmodulePulsesData.pxx.setupFrame(EXTERNAL_MODULE); - scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX_PULSES_PERIOD); return true; #endif #if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) case PROTOCOL_CHANNELS_PXX1_SERIAL: extmodulePulsesData.pxx_uart.setupFrame(EXTERNAL_MODULE); - scheduleNextMixerCalculation(EXTERNAL_MODULE, EXTMODULE_PXX1_SERIAL_PERIOD); return true; #endif @@ -316,14 +327,12 @@ bool setupPulsesExternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: case PROTOCOL_CHANNELS_PXX2_LOWSPEED: extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE); - scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX2_PERIOD); return true; #endif #if defined(SBUS) case PROTOCOL_CHANNELS_SBUS: setupPulsesSbus(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, SBUS_PERIOD); return true; #endif @@ -332,47 +341,61 @@ bool setupPulsesExternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_DSM2_DSM2: case PROTOCOL_CHANNELS_DSM2_DSMX: setupPulsesDSM2(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, DSM2_PERIOD); return true; #endif #if defined(CROSSFIRE) case PROTOCOL_CHANNELS_CROSSFIRE: + { + ModuleSyncStatus& status = getModuleSyncStatus(EXTERNAL_MODULE); + if (status.isValid()) + mixerSchedulerSetPeriod(EXTERNAL_MODULE, status.getAdjustedRefreshRate()); + else + mixerSchedulerSetPeriod(EXTERNAL_MODULE, CROSSFIRE_PERIOD); setupPulsesCrossfire(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, CROSSFIRE_PERIOD); return true; + } #endif #if defined(GHOST) case PROTOCOL_CHANNELS_GHOST: + { + ModuleSyncStatus& status = getModuleSyncStatus(EXTERNAL_MODULE); + if (status.isValid()) + mixerSchedulerSetPeriod(EXTERNAL_MODULE, status.getAdjustedRefreshRate()); + else + mixerSchedulerSetPeriod(EXTERNAL_MODULE, GHOST_PERIOD); setupPulsesGhost(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, GHOST_PERIOD); return true; + } #endif #if defined(MULTIMODULE) case PROTOCOL_CHANNELS_MULTIMODULE: + { + ModuleSyncStatus& status = getModuleSyncStatus(EXTERNAL_MODULE); + if (status.isValid()) + mixerSchedulerSetPeriod(EXTERNAL_MODULE, status.getAdjustedRefreshRate()); + else + mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD); setupPulsesMultiExternalModule(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, MULTIMODULE_PERIOD); return true; + } #endif #if defined(PPM) case PROTOCOL_CHANNELS_PPM: setupPulsesPPMExternalModule(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE)); return true; #endif #if defined(AFHDS3) case PROTOCOL_CHANNELS_AFHDS3: extmodulePulsesData.afhds3.setupFrame(); - scheduleNextMixerCalculation(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT); return true; #endif default: - scheduleNextMixerCalculation(EXTERNAL_MODULE, 50/*ms*/); return false; } } @@ -386,12 +409,24 @@ static void enablePulsesInternalModule(uint8_t protocol) #if defined(PXX1) && !defined(INTMODULE_USART) case PROTOCOL_CHANNELS_PXX1_PULSES: intmodulePxx1PulsesStart(); +#if defined(INTMODULE_HEARTBEAT) + // use backup trigger (1 ms later) + mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1000/*us*/); +#else + mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); +#endif break; #endif #if defined(PXX1) && defined(INTMODULE_USART) case PROTOCOL_CHANNELS_PXX1_SERIAL: intmodulePxx1SerialStart(); +#if defined(INTMODULE_HEARTBEAT) + // use backup trigger (1 ms later) + mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1000/*us*/); +#else + mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); +#endif break; #endif @@ -399,6 +434,13 @@ static void enablePulsesInternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: intmoduleSerialStart(PXX2_HIGHSPEED_BAUDRATE, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); resetAccessAuthenticationCount(); + +#if defined(INTMODULE_HEARTBEAT) + // use backup trigger (1 ms later) + mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD + 1000/*us*/); +#else + mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD); +#endif break; #endif @@ -406,17 +448,20 @@ static void enablePulsesInternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_MULTIMODULE: intmodulePulsesData.multi.initFrame(); intmoduleSerialStart(MULTIMODULE_BAUDRATE, true, USART_Parity_Even, USART_StopBits_2, USART_WordLength_9b); - intmoduleTimerStart(MULTIMODULE_PERIOD); + mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD); break; #endif #if defined(INTERNAL_MODULE_PPM) case PROTOCOL_CHANNELS_PPM: intmodulePpmStart(); + mixerSchedulerSetPeriod(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE)); break; #endif default: + // internal module stopped, set internal period to 0 and start the scheduler + mixerSchedulerSetPeriod(INTERNAL_MODULE, 0); break; } } @@ -427,18 +472,18 @@ bool setupPulsesInternalModule(uint8_t protocol) #if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART) case PROTOCOL_CHANNELS_PXX1_PULSES: intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE); - scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); +#if defined(INTMODULE_HEARTBEAT) + mixerSchedulerResetTimer(); + mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1000 /* backup */); +#else + mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); +#endif return true; #endif #if defined(PXX1) && defined(INTMODULE_USART) case PROTOCOL_CHANNELS_PXX1_SERIAL: intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE); -#if defined(INTMODULE_HEARTBEAT) - scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1 /* backup */); -#else - scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); -#endif return true; #endif @@ -447,15 +492,16 @@ bool setupPulsesInternalModule(uint8_t protocol) { bool result = intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE); if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) { - scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_TOOLS_PERIOD); + mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_TOOLS_PERIOD); } else { #if defined(INTMODULE_HEARTBEAT) - scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD + 1 /* backup */); + mixerSchedulerResetTimer(); + mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD + 1000 /* backup */); #else - scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD); + mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD); #endif - } + } return result; } #endif @@ -463,19 +509,20 @@ bool setupPulsesInternalModule(uint8_t protocol) #if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM) case PROTOCOL_CHANNELS_PPM: setupPulsesPPMInternalModule(); - scheduleNextMixerCalculation(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE)); + // probably useless, as the interval did not change since "enable" function + mixerSchedulerSetPeriod(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE)); return true; #endif #if defined(INTERNAL_MODULE_MULTI) case PROTOCOL_CHANNELS_MULTIMODULE: setupPulsesMultiInternalModule(); - scheduleNextMixerCalculation(INTERNAL_MODULE, MULTIMODULE_PERIOD); + mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD); return true; #endif default: - scheduleNextMixerCalculation(INTERNAL_MODULE, 10 /*ms*/); // used for USB sim for example + mixerSchedulerSetPeriod(INTERNAL_MODULE, 10000 /*us*/); // used for USB sim for example return false; } } diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 84ecee015..4a1fafe65 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -216,21 +216,20 @@ typedef Dsm2SerialPulsesData Dsm2PulsesData; PACK(struct Dsm2TimerPulsesData { pulse_duration_t pulses[MAX_PULSES_TRANSITIONS]; pulse_duration_t * ptr; - uint16_t rest; uint8_t index; }); typedef Dsm2TimerPulsesData Dsm2PulsesData; #endif #define PPM_PERIOD_HALF_US(module) ((g_model.moduleData[module].ppm.frameLength * 5 + 225) * 200) /*half us*/ -#define PPM_PERIOD(module) (PPM_PERIOD_HALF_US(module) / 2000) /*ms*/ +#define PPM_PERIOD(module) (PPM_PERIOD_HALF_US(module) / 2) /*us*/ #define DSM2_BAUDRATE 125000 -#define DSM2_PERIOD 22 /*ms*/ +#define DSM2_PERIOD 22000 /*us*/ #define SBUS_BAUDRATE 100000 #define SBUS_PERIOD_HALF_US ((g_model.moduleData[EXTERNAL_MODULE].sbus.refreshRate * 5 + 225) * 200) /*half us*/ -#define SBUS_PERIOD (SBUS_PERIOD_HALF_US / 2000) /*ms*/ +#define SBUS_PERIOD (SBUS_PERIOD_HALF_US / 2) /*us*/ #define MULTIMODULE_BAUDRATE 100000 -#define MULTIMODULE_PERIOD 7 /*ms*/ +#define MULTIMODULE_PERIOD 7000 /*us*/ #define CROSSFIRE_FRAME_MAXLEN 64 PACK(struct CrossfirePulsesData { diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index 5d0bfaf05..ae84d77b2 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -29,20 +29,20 @@ #define PXX2_LOWSPEED_BAUDRATE 230400 #define PXX2_HIGHSPEED_BAUDRATE 450000 -#define PXX2_PERIOD 4 // 4ms -#define PXX2_TOOLS_PERIOD 1 // 1ms +#define PXX2_PERIOD 4000/*us*/ +#define PXX2_TOOLS_PERIOD 1000/*us*/ #define PXX2_FRAME_MAXLENGTH 64 -#define PXX_PULSES_PERIOD 9/*ms*/ -#define EXTMODULE_PXX1_SERIAL_PERIOD 4/*ms*/ +#define PXX_PULSES_PERIOD 9000/*us*/ +#define EXTMODULE_PXX1_SERIAL_PERIOD 4000/*us*/ #define EXTMODULE_PXX1_SERIAL_BAUDRATE 420000 #if defined(PXX_FREQUENCY_HIGH) #define INTMODULE_PXX1_SERIAL_BAUDRATE 450000 - #define INTMODULE_PXX1_SERIAL_PERIOD 4/*ms*/ + #define INTMODULE_PXX1_SERIAL_PERIOD 4000/*us*/ #else #define INTMODULE_PXX1_SERIAL_BAUDRATE 115200 - #define INTMODULE_PXX1_SERIAL_PERIOD 9/*ms*/ + #define INTMODULE_PXX1_SERIAL_PERIOD 9000/*us*/ #endif // Used by the Sky9x family boards diff --git a/radio/src/pulses/sbus.cpp b/radio/src/pulses/sbus.cpp index a881730fc..e44abd642 100644 --- a/radio/src/pulses/sbus.cpp +++ b/radio/src/pulses/sbus.cpp @@ -55,7 +55,6 @@ static void _send_level(uint8_t v) *extmodulePulsesData.dsm2.ptr++ = v - 1; extmodulePulsesData.dsm2.index+=1; - extmodulePulsesData.dsm2.rest -=v; } void sendByteSbus(uint8_t b) // max 11 changes 0 10 10 10 10 P 1 @@ -113,7 +112,6 @@ void setupPulsesSbus() extmodulePulsesData.dsm2.serialByte = 0; extmodulePulsesData.dsm2.serialBitCount = 0; #else - extmodulePulsesData.dsm2.rest = SBUS_PERIOD_HALF_US; extmodulePulsesData.dsm2.index = 0; #endif diff --git a/radio/src/rtos.h b/radio/src/rtos.h index 6e42ebf30..a5dbd11b9 100644 --- a/radio/src/rtos.h +++ b/radio/src/rtos.h @@ -36,7 +36,9 @@ extern "C++" { typedef pthread_t RTOS_TASK_HANDLE; typedef pthread_mutex_t RTOS_MUTEX_HANDLE; + typedef uint32_t RTOS_FLAG_HANDLE; + typedef sem_t * RTOS_EVENT_HANDLE; extern uint64_t simuTimerMicros(void); @@ -76,16 +78,26 @@ extern "C++" { pthread_mutex_unlock(&mutex); } - static inline void RTOS_CREATE_FLAG(uint32_t &flag) + static inline void RTOS_CREATE_FLAG(RTOS_FLAG_HANDLE flag) { - flag = 0; // TODO: real flags (use semaphores?) } - static inline void RTOS_SET_FLAG(uint32_t &flag) + static inline void RTOS_SET_FLAG(RTOS_FLAG_HANDLE flag) { - flag = 1; } + static inline void RTOS_CLEAR_FLAG(RTOS_FLAG_HANDLE flag) + { + } + + static inline bool RTOS_WAIT_FLAG(RTOS_FLAG_HANDLE flag, uint32_t timeout) + { + simuSleep(timeout); + return false; + } + + #define RTOS_ISR_SET_FLAG RTOS_SET_FLAG + template class FakeTaskStack { @@ -146,6 +158,7 @@ template { return (uint32_t)(simuTimerMicros() / 1000); } + #elif defined(RTOS_COOS) #ifdef __cplusplus extern "C" { @@ -230,7 +243,18 @@ template #define RTOS_CREATE_FLAG(flag) flag = CoCreateFlag(false, false) #define RTOS_SET_FLAG(flag) (void)CoSetFlag(flag) + #define RTOS_CLEAR_FLAG(flag) (void)CoClearFlag(flag) + #define RTOS_WAIT_FLAG(flag,timeout) (CoWaitForSingleFlag(flag,timeout) == E_TIMEOUT) + static inline void RTOS_ISR_SET_FLAG(RTOS_FLAG_HANDLE flag) + { + CoEnterISR(); + CoSchedLock(); + isr_SetFlag(flag); + CoSchedUnlock(); + CoExitISR(); + } + #ifdef __cplusplus template class TaskStack diff --git a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp index 25544c33a..269b40854 100644 --- a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp +++ b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "mixer_scheduler.h" #if defined(INTMODULE_HEARTBEAT_GPIO) volatile HeartbeatCapture heartbeatCapture; @@ -77,6 +78,8 @@ void check_intmodule_heartbeat() heartbeatCapture.count++; #endif EXTI_ClearITPendingBit(INTMODULE_HEARTBEAT_EXTI_LINE); + + mixerSchedulerISRTrigger(); } } #endif diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp index 56b71d97c..794c49765 100755 --- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp @@ -45,12 +45,6 @@ void intmoduleStop() USART_DeInit(INTMODULE_USART); GPIO_ResetBits(INTMODULE_GPIO, INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN); - -#if defined(INTERNAL_MODULE_MULTI) - // stop pulses timer - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; -#endif } void intmodulePxx1SerialStart() @@ -103,28 +97,6 @@ void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, } } -#if defined(INTERNAL_MODULE_MULTI) -void intmoduleTimerStart(uint32_t periodMs) -{ - // Timer - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - INTMODULE_TIMER->ARR = periodMs * 2000; - INTMODULE_TIMER->CCR2 = (periodMs - 1) * 2000; - INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - INTMODULE_TIMER->CCMR2 = 0; - INTMODULE_TIMER->EGR = 1; // Restart - - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - - NVIC_EnableIRQ(INTMODULE_TIMER_IRQn); - NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); -} -#endif - #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) extern "C" void INTMODULE_USART_IRQHandler(void) { @@ -217,12 +189,3 @@ void intmoduleSendNextFrame() #endif } } - -#if defined(INTERNAL_MODULE_MULTI) -extern "C" void INTMODULE_TIMER_IRQHandler() -{ - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag - setupPulsesInternalModule(); - intmoduleSendNextFrame(); -} -#endif diff --git a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp new file mode 100644 index 000000000..7f7b23a1c --- /dev/null +++ b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "opentx.h" +#include "mixer_scheduler.h" + +#if !defined(SIMU) + +// Start scheduler with default period +void mixerSchedulerStart() +{ + MIXER_SCHEDULER_TIMER->CR1 &= ~TIM_CR1_CEN; + + MIXER_SCHEDULER_TIMER->CR1 = TIM_CR1_URS; // do not generate interrupt on soft update + MIXER_SCHEDULER_TIMER->PSC = MIXER_SCHEDULER_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + MIXER_SCHEDULER_TIMER->CCER = 0; + MIXER_SCHEDULER_TIMER->CCMR1 = 0; + MIXER_SCHEDULER_TIMER->ARR = 2 * getMixerSchedulerPeriod() - 1; + MIXER_SCHEDULER_TIMER->EGR = TIM_EGR_UG; // reset timer + + NVIC_EnableIRQ(MIXER_SCHEDULER_TIMER_IRQn); + NVIC_SetPriority(MIXER_SCHEDULER_TIMER_IRQn, 8); + + MIXER_SCHEDULER_TIMER->SR &= TIM_SR_UIF; // clear interrupt flag + MIXER_SCHEDULER_TIMER->DIER |= TIM_DIER_UIE; // enable interrupt + MIXER_SCHEDULER_TIMER->CR1 |= TIM_CR1_CEN; +} + +void mixerSchedulerStop() +{ + MIXER_SCHEDULER_TIMER->CR1 &= ~TIM_CR1_CEN; + NVIC_DisableIRQ(MIXER_SCHEDULER_TIMER_IRQn); +} + +void mixerSchedulerResetTimer() +{ + mixerSchedulerDisableTrigger(); + MIXER_SCHEDULER_TIMER->CNT = 0; + mixerSchedulerEnableTrigger(); +} + +void mixerSchedulerEnableTrigger() +{ + MIXER_SCHEDULER_TIMER->DIER |= TIM_DIER_UIE; // enable interrupt +} + +void mixerSchedulerDisableTrigger() +{ + MIXER_SCHEDULER_TIMER->DIER &= ~TIM_DIER_UIE; // disable interrupt +} + +extern "C" void MIXER_SCHEDULER_TIMER_IRQHandler(void) +{ + MIXER_SCHEDULER_TIMER->SR &= ~TIM_SR_UIF; // clear flag + mixerSchedulerDisableTrigger(); + + // set next period + MIXER_SCHEDULER_TIMER->ARR = 2 * getMixerSchedulerPeriod() - 1; + + // trigger mixer start + mixerSchedulerISRTrigger(); +} + +#endif diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index fbf963b71..460a24701 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -240,6 +240,7 @@ set(TARGET_SRC led_driver.cpp extmodule_driver.cpp trainer_driver.cpp + ../common/arm/stm32/mixer_scheduler_driver.cpp ../common/arm/stm32/heartbeat_driver.cpp ../common/arm/stm32/timers_driver.cpp ../common/arm/stm32/intmodule_serial_driver.cpp diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index cb379e6fe..0f3f9df4a 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -137,6 +137,7 @@ void boardInit() INTMODULE_RCC_APB1Periph | EXTMODULE_RCC_APB1Periph | I2C_RCC_APB1Periph | + MIXER_SCHEDULER_TIMER_RCC_APB1Periph | GPS_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph, ENABLE); diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 38daec33c..f1c47ab9f 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -180,14 +180,11 @@ void init_intmodule_heartbeat(); void check_intmodule_heartbeat(); void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength); -#if defined(INTERNAL_MODULE_MULTI) -void intmoduleTimerStart(uint32_t periodMs); -#endif void intmoduleSendByte(uint8_t byte); void intmoduleSendBuffer(const uint8_t * data, uint8_t size); void intmoduleSendNextFrame(); -void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inverted); +void extmoduleSerialStart(); void extmoduleInvertedSerialStart(uint32_t baudrate); void extmoduleSendBuffer(const uint8_t * data, uint8_t size); void extmoduleSendNextFrame(); diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 47a40ae02..e73d5c3d3 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -143,7 +143,7 @@ void extmodulePxx1PulsesStart() } #endif -void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us, bool inverted) +void extmoduleSerialStart() { EXTERNAL_MODULE_ON(); @@ -176,10 +176,9 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us, bool i EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; #endif - EXTMODULE_TIMER->ARR = period_half_us; - EXTMODULE_TIMER->CCR2 = period_half_us - 4000; + EXTMODULE_TIMER->ARR = 40000; // dummy value until the DMA request kicks in EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_UDE | TIM_DIER_CC2IE; + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn); @@ -342,23 +341,36 @@ void extmoduleSendNextFrame() #if defined(DSM2) case PROTOCOL_CHANNELS_SBUS: -#if defined(PCBX10) || PCBREV >= 13 - EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0); // reverse polarity for Sbus if needed -#else - EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0); // reverse polarity for Sbus if needed -#endif - // no break case PROTOCOL_CHANNELS_DSM2_LP45: case PROTOCOL_CHANNELS_DSM2_DSM2: case PROTOCOL_CHANNELS_DSM2_DSMX: case PROTOCOL_CHANNELS_MULTIMODULE: - EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.dsm2.ptr - 1) - 4000; // 2mS in advance + + if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) + return; + + if (PROTOCOL_CHANNELS_SBUS == moduleState[EXTERNAL_MODULE].protocol) { +#if defined(PCBX10) || PCBREV >= 13 + EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0); // reverse polarity for Sbus if needed +#else + EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0); // reverse polarity for Sbus if needed +#endif + } + + // disable timer + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + + // send DMA request EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses); EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses; EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + + // re-init timer + EXTMODULE_TIMER->EGR = 1; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; break; #endif @@ -419,14 +431,20 @@ extern "C" void EXTMODULE_TIMER_DMA_IRQHandler() DMA_ClearITPendingBit(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC); - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + switch (moduleState[EXTERNAL_MODULE].protocol) { + case PROTOCOL_CHANNELS_PXX1_PULSES: + case PROTOCOL_CHANNELS_PPM: + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + break; + } } extern "C" void EXTMODULE_TIMER_IRQHandler() { EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; + if (setupPulsesExternalModule()) extmoduleSendNextFrame(); } diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 479dd88c5..35a135cf4 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -902,6 +902,13 @@ #define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7 #define TIMER_2MHz_TIMER TIM7 +// Mixer scheduler timer +#define MIXER_SCHEDULER_TIMER_RCC_APB1Periph RCC_APB1Periph_TIM13 +#define MIXER_SCHEDULER_TIMER TIM13 +#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#define MIXER_SCHEDULER_TIMER_IRQn TIM8_UP_TIM13_IRQn +#define MIXER_SCHEDULER_TIMER_IRQHandler TIM8_UP_TIM13_IRQHandler + // Bluetooth #define STORAGE_BLUETOOTH #if defined(BLUETOOTH) diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 506f237cd..955a0994c 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -401,6 +401,7 @@ set(TARGET_SRC ../common/arm/stm32/audio_dac_driver.cpp ../common/arm/stm32/adc_driver.cpp ../common/arm/stm32/heartbeat_driver.cpp + ../common/arm/stm32/mixer_scheduler_driver.cpp ) if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES) diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index b038fc0f7..7d8561636 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -110,6 +110,7 @@ void boardInit() AUX_SERIAL_RCC_APB1Periph | INTMODULE_RCC_APB1Periph | TRAINER_MODULE_RCC_APB1Periph | + MIXER_SCHEDULER_TIMER_RCC_APB1Periph | BT_RCC_APB1Periph | GYRO_RCC_APB1Periph, ENABLE); @@ -339,4 +340,4 @@ void initJackDetect(void) GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(JACK_DETECT_GPIO, &GPIO_InitStructure); } -#endif \ No newline at end of file +#endif diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index d9092fcdc..29fd50432 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -143,7 +143,7 @@ void intmoduleSendByte(uint8_t byte); void intmoduleSendBuffer(const uint8_t * data, uint8_t size); void intmoduleSendNextFrame(); -void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inverted); +void extmoduleSerialStart(); void extmoduleInvertedSerialStart(uint32_t baudrate); void extmoduleSendBuffer(const uint8_t * data, uint8_t size); void extmoduleSendNextFrame(); diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 4287c0f75..7a7927a41 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -83,7 +83,7 @@ void extmodulePpmStart() NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); } -void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us, bool inverted) +void extmoduleSerialStart() { EXTERNAL_MODULE_ON(); @@ -99,16 +99,17 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us, bool i EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz - EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (inverted ? 0 : EXTMODULE_TIMER_OUTPUT_POLARITY); + + EXTMODULE_TIMER->CCR3 = 0; + EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | EXTMODULE_TIMER_OUTPUT_POLARITY; EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs EXTMODULE_TIMER->CCR1 = 0; EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high EXTMODULE_TIMER->EGR = 1; // Restart EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; - EXTMODULE_TIMER->ARR = period_half_us; - EXTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms + EXTMODULE_TIMER->ARR = 40000; // dummy value until the DMA request kicks in EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_UDE | TIM_DIER_CC2IE; + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn); @@ -300,19 +301,33 @@ void extmoduleSendNextFrame() #endif #if defined(SBUS) || defined(DSM2) || defined(MULTIMODULE) case PROTOCOL_CHANNELS_SBUS: - EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? 0 : EXTMODULE_TIMER_OUTPUT_POLARITY); // reverse polarity for Sbus if needed // no break case PROTOCOL_CHANNELS_DSM2_LP45: case PROTOCOL_CHANNELS_DSM2_DSM2: case PROTOCOL_CHANNELS_DSM2_DSMX: case PROTOCOL_CHANNELS_MULTIMODULE: - EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.dsm2.ptr - 1) - 4000; // 2mS in advance + + if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) + return; + + if (PROTOCOL_CHANNELS_SBUS == moduleState[EXTERNAL_MODULE].protocol) { + EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // reverse polarity for Sbus if needed + } + + // disable timer + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + + // send DMA request EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses); EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses; EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + + // re-init timer + EXTMODULE_TIMER->EGR = 1; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; break; #endif @@ -373,14 +388,20 @@ extern "C" void EXTMODULE_TIMER_DMA_STREAM_IRQHandler() DMA_ClearITPendingBit(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC); - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + switch (moduleState[EXTERNAL_MODULE].protocol) { + case PROTOCOL_CHANNELS_PXX1_PULSES: + case PROTOCOL_CHANNELS_PPM: + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + break; + } } extern "C" void EXTMODULE_TIMER_CC_IRQHandler() { EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; + if (setupPulsesExternalModule()) { extmoduleSendNextFrame(); } diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index b7160cbf9..aebff4c88 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -2024,4 +2024,11 @@ #define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7 #define TIMER_2MHz_TIMER TIM7 +// Mixer scheduler timer +#define MIXER_SCHEDULER_TIMER_RCC_APB1Periph RCC_APB1Periph_TIM13 +#define MIXER_SCHEDULER_TIMER TIM13 +#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#define MIXER_SCHEDULER_TIMER_IRQn TIM8_UP_TIM13_IRQn +#define MIXER_SCHEDULER_TIMER_IRQHandler TIM8_UP_TIM13_IRQHandler + #endif // _HAL_H_ diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 16e120784..e4c209edd 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "mixer_scheduler.h" RTOS_TASK_HANDLE menusTaskId; RTOS_DEFINE_STACK(menusStack, MENUS_STACK_SIZE); @@ -75,13 +76,29 @@ bool isForcePowerOffRequested() bool isModuleSynchronous(uint8_t moduleIdx) { - uint8_t protocol = moduleState[moduleIdx].protocol; - if (protocol == PROTOCOL_CHANNELS_PXX2_HIGHSPEED || protocol == PROTOCOL_CHANNELS_PXX2_LOWSPEED || protocol == PROTOCOL_CHANNELS_CROSSFIRE || protocol == PROTOCOL_CHANNELS_GHOST || protocol == PROTOCOL_CHANNELS_NONE) - return true; -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) - if (protocol == PROTOCOL_CHANNELS_PXX1_SERIAL) - return true; + switch(moduleState[moduleIdx].protocol) { + + case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: + case PROTOCOL_CHANNELS_PXX2_LOWSPEED: + case PROTOCOL_CHANNELS_CROSSFIRE: + case PROTOCOL_CHANNELS_GHOST: + case PROTOCOL_CHANNELS_AFHDS3: + case PROTOCOL_CHANNELS_NONE: + +#if defined(MULTIMODULE) + case PROTOCOL_CHANNELS_MULTIMODULE: #endif +#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) + case PROTOCOL_CHANNELS_PXX1_SERIAL: +#endif +#if defined(DSM2) + case PROTOCOL_CHANNELS_SBUS: + case PROTOCOL_CHANNELS_DSM2_LP45: + case PROTOCOL_CHANNELS_DSM2_DSM2: + case PROTOCOL_CHANNELS_DSM2_DSMX: +#endif + return true; + } return false; } @@ -100,12 +117,17 @@ void sendSynchronousPulses(uint8_t runMask) } } +//#define DEBUG_MIXER_SCHEDULER + uint32_t nextMixerTime[NUM_MODULES]; TASK_FUNCTION(mixerTask) { s_pulses_paused = true; + mixerSchedulerInit(); + mixerSchedulerStart(); + while (true) { #if defined(SBUS_TRAINER) // SBUS trainer @@ -120,7 +142,16 @@ TASK_FUNCTION(mixerTask) bluetooth.wakeup(); #endif - RTOS_WAIT_TICKS(1); + // run mixer at least every 30ms + bool timeout = mixerSchedulerWaitForTrigger(30); + +#if defined(DEBUG_MIXER_SCHEDULER) + GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); +#endif + + // re-enable trigger + mixerSchedulerEnableTrigger(); #if defined(SIMU) if (pwrCheck() == e_power_off) { @@ -132,23 +163,6 @@ TASK_FUNCTION(mixerTask) } #endif - uint32_t now = RTOS_GET_MS(); - uint8_t runMask = 0; - - if (now >= nextMixerTime[0]) { - runMask |= (1 << 0); - } - -#if NUM_MODULES >= 2 - if (now >= nextMixerTime[1]) { - runMask |= (1 << 1); - } -#endif - - if (!runMask) { - continue; // go back to sleep - } - if (!s_pulses_paused) { uint16_t t0 = getTmr2MHz(); @@ -183,29 +197,18 @@ TASK_FUNCTION(mixerTask) if (t0 > maxMixerDuration) maxMixerDuration = t0; - sendSynchronousPulses(runMask); + // TODO: + // - check the cause of timeouts when switching + // between protocols with multi-proto RF + if (timeout) + serialPrint("mix sched timeout!"); + + // TODO: fix runMask + sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE)); } } } -void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms) -{ - // Schedule next mixer calculation time, - - if (isModuleSynchronous(module)) { - nextMixerTime[module] += period_ms / RTOS_MS_PER_TICK; - if (nextMixerTime[module] < RTOS_GET_TIME()) { - // we are late ... let's add some small delay - nextMixerTime[module] = (uint32_t) RTOS_GET_TIME() + (period_ms / RTOS_MS_PER_TICK); - } - } - else { - // for now assume mixer calculation takes 2 ms. - nextMixerTime[module] = (uint32_t) RTOS_GET_TIME() + (period_ms / RTOS_MS_PER_TICK); - } - - DEBUG_TIMER_STOP(debugTimerMixerCalcToUsage); -} #define MENU_TASK_PERIOD_TICKS (50 / RTOS_MS_PER_TICK) // 50ms diff --git a/radio/src/telemetry/crossfire.cpp b/radio/src/telemetry/crossfire.cpp index b46cc2b44..672dd56f0 100644 --- a/radio/src/telemetry/crossfire.cpp +++ b/radio/src/telemetry/crossfire.cpp @@ -184,6 +184,26 @@ void processCrossfireTelemetryFrame() break; } + case RADIO_ID: + if (telemetryRxBuffer[3] == 0xEA // radio address + && telemetryRxBuffer[5] == 0x10 // timing correction frame + ) { + + uint32_t update_interval; + int32_t offset; + if (getCrossfireTelemetryValue<4>(6, (int32_t&)update_interval) && getCrossfireTelemetryValue<4>(10, offset)) { + + // values are in 10th of micro-seconds + update_interval /= 10; + offset /= 10; + + TRACE("[XF] Rate: %d, Lag: %d", update_interval, offset); + getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset + SAFE_SYNC_LAG); + } + } + break; + + #if defined(LUA) default: if (luaInputTelemetryFifo && luaInputTelemetryFifo->hasSpace(telemetryRxBufferCount-2) ) { diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h index 9855b78f4..9940986f9 100644 --- a/radio/src/telemetry/crossfire.h +++ b/radio/src/telemetry/crossfire.h @@ -99,15 +99,15 @@ const uint32_t CROSSFIRE_BAUDRATES[] = { 115200, }; const uint8_t CROSSFIRE_PERIODS[] = { - 4, + 4, 16, }; #if SPORT_MAX_BAUDRATE < 400000 #define CROSSFIRE_BAUDRATE CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate] -#define CROSSFIRE_PERIOD CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate] +#define CROSSFIRE_PERIOD (CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate]*1000) #else #define CROSSFIRE_BAUDRATE 400000 -#define CROSSFIRE_PERIOD 4 // 4ms +#define CROSSFIRE_PERIOD 6666 /* us; 150 Hz */ #endif #define CROSSFIRE_TELEM_MIRROR_BAUDRATE 115200 diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index b1b86eb0a..eb5f6fc08 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -63,7 +63,6 @@ enum MultiBufferState : uint8_t #if defined(INTERNAL_MODULE_MULTI) static MultiModuleStatus multiModuleStatus[NUM_MODULES] = {MultiModuleStatus(), MultiModuleStatus()}; -static MultiModuleSyncStatus multiSyncStatus[NUM_MODULES] = {MultiModuleSyncStatus(), MultiModuleSyncStatus()}; static uint8_t multiBindStatus[NUM_MODULES] = {MULTI_NORMAL_OPERATION, MULTI_NORMAL_OPERATION}; static MultiBufferState multiTelemetryBufferState[NUM_MODULES]; @@ -74,11 +73,6 @@ MultiModuleStatus &getMultiModuleStatus(uint8_t module) return multiModuleStatus[module]; } -MultiModuleSyncStatus &getMultiSyncStatus(uint8_t module) -{ - return multiSyncStatus[module]; -} - uint8_t getMultiBindStatus(uint8_t module) { return multiBindStatus[module]; @@ -111,7 +105,6 @@ uint8_t intTelemetryRxBufferCount; #else // !INTERNAL_MODULE_MULTI static MultiModuleStatus multiModuleStatus; -static MultiModuleSyncStatus multiSyncStatus; static uint8_t multiBindStatus = MULTI_NORMAL_OPERATION; static MultiBufferState multiTelemetryBufferState; @@ -122,11 +115,6 @@ MultiModuleStatus& getMultiModuleStatus(uint8_t) return multiModuleStatus; } -MultiModuleSyncStatus& getMultiSyncStatus(uint8_t) -{ - return multiSyncStatus; -} - uint8_t getMultiBindStatus(uint8_t) { return multiBindStatus; @@ -254,24 +242,17 @@ static void processMultiStatusPacket(const uint8_t * data, uint8_t module, uint8 static void processMultiSyncPacket(const uint8_t * data, uint8_t module) { - MultiModuleSyncStatus &status = getMultiSyncStatus(module); + ModuleSyncStatus &status = getModuleSyncStatus(module); - status.lastUpdate = get_tmr10ms(); - status.interval = data[4]; - status.target = data[5]; -#if !defined(PPM_PIN_SERIAL) - auto oldlag = status.inputLag; - (void) oldlag; -#endif + uint16_t refreshRate = data[0] << 8 | data[1]; + int16_t inputLag = data[2] << 8 | data[3]; - status.calcAdjustedRefreshRate(data[0] << 8 | data[1], data[2] << 8 | data[3]); + // if (inputLag > refreshRate/2) + // inputLag -= refreshRate; -#if !defined(PPM_PIN_SERIAL) - TRACE("MP ADJ: rest: %d, lag %04d, diff: %04d target: %d, interval: %d, Refresh: %d, intAdjRefresh: %d, adjRefresh %d\r\n", - module == EXTERNAL_MODULE ? extmodulePulsesData.dsm2.rest : 0, - status.inputLag, oldlag - status.inputLag, status.target, status.interval, status.refreshRate, status.adjustedRefreshRate / 50, - status.getAdjustedRefreshRate()); -#endif + status.update(refreshRate, inputLag); + + serialPrint("MP ADJ: R %d, L %04d", refreshRate, inputLag); } #if defined(PCBTARANIS) || defined(PCBHORUS) @@ -434,104 +415,6 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) } } -#define MIN_REFRESH_RATE 5500 - -void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uint16_t newInputLag) -{ - // Check how far off we are from our target, positive means we are too slow, negative we are too fast - int lagDifference = newInputLag - inputLag; - - // The refresh rate that we target - // Below is least common multiple of MIN_REFRESH_RATE and requested rate - uint16_t targetRefreshRate = (uint16_t) (newRefreshRate * ((MIN_REFRESH_RATE / (newRefreshRate - 1)) + 1)); - - // Overflow, reverse sample - if (lagDifference < -targetRefreshRate / 2) - lagDifference = -lagDifference; - - - // Reset adjusted refresh if rate has changed - if (newRefreshRate != refreshRate) { - refreshRate = newRefreshRate; - adjustedRefreshRate = targetRefreshRate; - if (adjustedRefreshRate >= 30000) - adjustedRefreshRate /= 2; - - // Our refresh rate in ps - adjustedRefreshRate *= 1000; - return; - } - - // Caluclate how many samples went into the reported input Lag (*10) - int numsamples = interval * 10000 / targetRefreshRate; - - // Convert lagDifference to ps - lagDifference = lagDifference * 1000; - - // Calculate the time we intentionally were late/early - if (inputLag > target * 10 + 30) - lagDifference += numsamples * 500; - else if (inputLag < target * 10 - 30) - lagDifference -= numsamples * 500; - - // Caculate the time in ps each frame is to slow (positive), fast(negative) - int perframeps = lagDifference * 10 / numsamples; - - if (perframeps > 20000) - perframeps = 20000; - - if (perframeps < -20000) - perframeps = -20000; - - adjustedRefreshRate = (adjustedRefreshRate + perframeps); - - // Safeguards - if (adjustedRefreshRate < MIN_REFRESH_RATE * 1000) - adjustedRefreshRate = MIN_REFRESH_RATE * 1000; - if (adjustedRefreshRate > 30 * 1000 * 1000) - adjustedRefreshRate = 30 * 1000 * 1000; - - inputLag = newInputLag; -} - -static uint8_t counter; - -const uint16_t MultiModuleSyncStatus::getAdjustedRefreshRate() -{ - if (!isValid() || refreshRate == 0) - return 18000; - - counter = (uint8_t) (counter + 1 % 10); - uint16_t rate = (uint16_t) ((adjustedRefreshRate + counter * 50) / 500); - // Check how far off we are from our target, positive means we are too slow, negative we are too fast - if (inputLag > target * 10 + 30) - return (uint16_t) (rate - 1); - else if (inputLag < target * 10 - 30) - return (uint16_t) (rate + 1); - else - return rate; -} - -void MultiModuleSyncStatus::getRefreshString(char * statusText) -{ - if (!isValid()) { - return; - } - - char * tmp = statusText; -#if defined(DEBUG) - *tmp++ = 'L'; - tmp = strAppendUnsigned(tmp, inputLag, 5); - tmp = strAppend(tmp, "us R "); - tmp = strAppendUnsigned(tmp, (uint32_t) (adjustedRefreshRate / 1000), 5); - tmp = strAppend(tmp, "us"); -#else - tmp = strAppend(tmp, "Sync at "); - tmp = strAppendUnsigned(tmp, (uint32_t) (adjustedRefreshRate / 1000000)); - tmp = strAppend(tmp, " ms"); -#endif -} - void MultiModuleStatus::getStatusString(char * statusText) const { if (!isValid()) { diff --git a/radio/src/telemetry/multi.h b/radio/src/telemetry/multi.h index e9b9ada15..ca9d3fc79 100644 --- a/radio/src/telemetry/multi.h +++ b/radio/src/telemetry/multi.h @@ -94,28 +94,6 @@ void processMultiTelemetryData(uint8_t data, uint8_t module); #define MULTI_SCANNER_MAX_CHANNEL 249 -// This should be put into the Module definition if other modules gain this functionality -struct MultiModuleSyncStatus { - uint32_t adjustedRefreshRate = 9000 * 1000; // in ps - tmr10ms_t lastUpdate; - uint16_t refreshRate; - uint16_t inputLag; - uint8_t interval; - uint8_t target; - - inline bool isValid() const - { - return (get_tmr10ms() - lastUpdate < 100); - } - - void getRefreshString(char * refreshText); - const uint16_t getAdjustedRefreshRate(); - void calcAdjustedRefreshRate(uint16_t newRefreshRate, uint16_t newInputLag); -}; - -MultiModuleSyncStatus& getMultiSyncStatus(uint8_t module); - - struct MultiModuleStatus { uint8_t major; diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 70c4fdc74..21e1e6d9b 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -21,6 +21,7 @@ #include "opentx.h" #include "multi.h" #include "pulses/afhds3.h" +#include "mixer_scheduler.h" 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) @@ -374,3 +375,88 @@ OutputTelemetryBuffer outputTelemetryBuffer __DMA; #if defined(LUA) Fifo * luaInputTelemetryFifo = NULL; #endif + +#if defined(HARDWARE_INTERNAL_MODULE) + +static ModuleSyncStatus moduleSyncStatus[NUM_MODULES]; + +ModuleSyncStatus &getModuleSyncStatus(uint8_t moduleIdx) +{ + return moduleSyncStatus[moduleIdx]; +} + +#else + +static ModuleSyncStatus moduleSyncStatus; + +ModuleSyncStatus &getModuleSyncStatus(uint8_t moduleIdx) +{ + return moduleSyncStatus; +} + +#endif + +ModuleSyncStatus::ModuleSyncStatus() +{ + memset(this, 0, sizeof(ModuleSyncStatus)); +} + +void ModuleSyncStatus::update(uint16_t newRefreshRate, uint16_t newInputLag) +{ + if (!newRefreshRate) + return; + + if (newRefreshRate < MIN_REFRESH_RATE) + newRefreshRate = newRefreshRate * (MIN_REFRESH_RATE / (newRefreshRate + 1)); + else if (newRefreshRate > MAX_REFRESH_RATE) + newRefreshRate = MAX_REFRESH_RATE; + + refreshRate = newRefreshRate; + inputLag = newInputLag; + currentLag = newInputLag; + lastUpdate = get_tmr10ms(); +} + +uint16_t ModuleSyncStatus::getAdjustedRefreshRate() +{ + int16_t lag = currentLag - SAFE_SYNC_LAG; + int32_t newRefreshRate = refreshRate; + + if (lag == 0) { + return refreshRate; + } + + newRefreshRate += lag; + + if (newRefreshRate < MIN_REFRESH_RATE) { + newRefreshRate = MIN_REFRESH_RATE; + } + else if (newRefreshRate > MAX_REFRESH_RATE) { + newRefreshRate = MAX_REFRESH_RATE; + } + + TRACE("[SYNC] rate = %dus",newRefreshRate); + + currentLag -= newRefreshRate - refreshRate; + return (uint16_t)newRefreshRate; +} + +void ModuleSyncStatus::getRefreshString(char * statusText) +{ + if (!isValid()) { + return; + } + + char * tmp = statusText; +#if defined(DEBUG) + *tmp++ = 'L'; + tmp = strAppendUnsigned(tmp, inputLag, 5); + tmp = strAppend(tmp, "us R "); + tmp = strAppendUnsigned(tmp, (uint32_t) (refreshRate / 1000), 5); + tmp = strAppend(tmp, "us"); +#else + tmp = strAppend(tmp, "Sync at "); + tmp = strAppendUnsigned(tmp, (uint32_t) (refreshRate / 1000000)); + tmp = strAppend(tmp, " ms"); +#endif +} diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 6599db749..18f4f98a6 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -289,4 +289,35 @@ extern Fifo * luaInputTelemetryFifo; void processPXX2Frame(uint8_t module, const uint8_t *frame); +// Module pulse synchronization +#define SAFE_SYNC_LAG 800 /* us */ + +struct ModuleSyncStatus +{ + // feedback input: last received values + uint16_t refreshRate; // in us + int16_t inputLag; // in us + + tmr10ms_t lastUpdate; // in 10ms + int16_t currentLag; // in us + + inline bool isValid() { + // 2 seconds + return (get_tmr10ms() - lastUpdate < 200); + } + + // Set feedback from RF module + void update(uint16_t newRefreshRate, uint16_t newInputLag); + + // Get computed settings for scheduler + uint16_t getAdjustedRefreshRate(); + + // Status string for the UI + void getRefreshString(char* refreshText); + + ModuleSyncStatus(); +}; + +ModuleSyncStatus& getModuleSyncStatus(uint8_t moduleIdx); + #endif // _TELEMETRY_H_ From 63438b06d76735f7ae176767f8d563268773761e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 10:06:37 +0200 Subject: [PATCH 02/37] restored 250Hz default rate for crossfire at 400kbps --- radio/src/telemetry/crossfire.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h index 9940986f9..376b1fec4 100644 --- a/radio/src/telemetry/crossfire.h +++ b/radio/src/telemetry/crossfire.h @@ -107,7 +107,7 @@ const uint8_t CROSSFIRE_PERIODS[] = { #define CROSSFIRE_PERIOD (CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate]*1000) #else #define CROSSFIRE_BAUDRATE 400000 -#define CROSSFIRE_PERIOD 6666 /* us; 150 Hz */ +#define CROSSFIRE_PERIOD 4000 /* us; 250 Hz */ #endif #define CROSSFIRE_TELEM_MIRROR_BAUDRATE 115200 From 8247a05438bae4992a0cbbea6db3c5ae0b8c8de5 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 10:41:20 +0200 Subject: [PATCH 03/37] debugging crsfshot... --- radio/src/pulses/pulses.cpp | 2 +- radio/src/telemetry/telemetry.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 1681157bc..d21c58853 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -522,7 +522,7 @@ bool setupPulsesInternalModule(uint8_t protocol) #endif default: - mixerSchedulerSetPeriod(INTERNAL_MODULE, 10000 /*us*/); // used for USB sim for example + //mixerSchedulerSetPeriod(INTERNAL_MODULE, 10000 /*us*/); // used for USB sim for example return false; } } diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 21e1e6d9b..44906b9d7 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -415,6 +415,8 @@ void ModuleSyncStatus::update(uint16_t newRefreshRate, uint16_t newInputLag) inputLag = newInputLag; currentLag = newInputLag; lastUpdate = get_tmr10ms(); + + TRACE("[SYNC] update rate = %dus; lag = %dus",refreshRate,currentLag); } uint16_t ModuleSyncStatus::getAdjustedRefreshRate() @@ -435,9 +437,9 @@ uint16_t ModuleSyncStatus::getAdjustedRefreshRate() newRefreshRate = MAX_REFRESH_RATE; } - TRACE("[SYNC] rate = %dus",newRefreshRate); - currentLag -= newRefreshRate - refreshRate; + TRACE("[SYNC] mod rate = %dus; lag = %dus",newRefreshRate,currentLag); + return (uint16_t)newRefreshRate; } From ef3b669d38c1742b95cc0327935fba244ff22e94 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 11:16:00 +0200 Subject: [PATCH 04/37] fixed Ghost sync feedback --- radio/src/telemetry/ghost.cpp | 13 +++++++++++++ radio/src/telemetry/ghost.h | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/radio/src/telemetry/ghost.cpp b/radio/src/telemetry/ghost.cpp index 098e9c990..2095a3710 100755 --- a/radio/src/telemetry/ghost.cpp +++ b/radio/src/telemetry/ghost.cpp @@ -132,6 +132,19 @@ void processGhostTelemetryFrame() uint8_t id = telemetryRxBuffer[2]; switch(id) { + case GHST_DL_OPENTX_SYNC: + { + uint32_t update_interval = getTelemetryValue_s32(3); + int32_t offset = getTelemetryValue_s32(7); + + // values are in units of 100ns + update_interval /= 10; + offset /= 10; + + getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset + SAFE_SYNC_LAG); + } + break; + case GHST_DL_LINK_STAT: { #if defined(BLUETOOTH) diff --git a/radio/src/telemetry/ghost.h b/radio/src/telemetry/ghost.h index 0a3195835..9cdd48a39 100755 --- a/radio/src/telemetry/ghost.h +++ b/radio/src/telemetry/ghost.h @@ -113,7 +113,7 @@ enum GhostTelemetryBaudrates }; #endif #define GHOST_BAUDRATE 400000 -#define GHOST_PERIOD 4 +#define GHOST_PERIOD 4000 /* us */ enum GhostLineFlags { From 92f27a853ae16c194ccc302bc6b2a4a03e5be748 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 12:07:09 +0200 Subject: [PATCH 05/37] moved sync pulse sending to *before* periodic mixer processing This should enable a more stable pulse sending to the module. --- radio/src/opentx.cpp | 13 +++++++++++++ radio/src/opentx.h | 1 + radio/src/tasks.cpp | 11 ++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 73b39c407..bebb5b317 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1426,6 +1426,19 @@ void doMixerCalculations() DEBUG_TIMER_START(debugTimerEvalMixes); evalMixes(tick10ms); DEBUG_TIMER_STOP(debugTimerEvalMixes); +} + +void doMixerPeriodicUpdates() +{ + static tmr10ms_t lastTMR = 0; + + tmr10ms_t tmr10ms = get_tmr10ms(); + + uint8_t tick10ms = (tmr10ms >= lastTMR ? tmr10ms - lastTMR : 1); + // handle tick10ms overrun + // correct overflow handling costs a lot of code; happens only each 11 min; + // therefore forget the exact calculation and use only 1 instead; good compromise + lastTMR = tmr10ms; DEBUG_TIMER_START(debugTimerMixes10ms); if (tick10ms) { diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 394a0734f..6d028ff06 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -483,6 +483,7 @@ extern uint32_t nextMixerTime[NUM_MODULES]; void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms); void evalMixes(uint8_t tick10ms); void doMixerCalculations(); +void doMixerPeriodicUpdates(); void checkTrims(); extern uint8_t currentBacklightBright; diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index e4c209edd..431ed7e52 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -168,12 +168,20 @@ TASK_FUNCTION(mixerTask) DEBUG_TIMER_START(debugTimerMixer); RTOS_LOCK_MUTEX(mixerMutex); + doMixerCalculations(); + + // TODO: fix runMask + sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE)); + + doMixerPeriodicUpdates(); + DEBUG_TIMER_START(debugTimerMixerCalcToUsage); DEBUG_TIMER_SAMPLE(debugTimerMixerIterval); RTOS_UNLOCK_MUTEX(mixerMutex); DEBUG_TIMER_STOP(debugTimerMixer); + #if defined(STM32) && !defined(SIMU) if (getSelectedUsbMode() == USB_JOYSTICK_MODE) { usbJoystickUpdate(); @@ -202,9 +210,6 @@ TASK_FUNCTION(mixerTask) // between protocols with multi-proto RF if (timeout) serialPrint("mix sched timeout!"); - - // TODO: fix runMask - sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE)); } } } From dd4c91ce4f86b6018ea1b8af400e591c7697f3f3 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 12:17:05 +0200 Subject: [PATCH 06/37] removed SAFE_SYNC_LAG --- radio/src/telemetry/crossfire.cpp | 2 +- radio/src/telemetry/ghost.cpp | 2 +- radio/src/telemetry/telemetry.cpp | 2 +- radio/src/telemetry/telemetry.h | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/radio/src/telemetry/crossfire.cpp b/radio/src/telemetry/crossfire.cpp index 672dd56f0..173ea38f4 100644 --- a/radio/src/telemetry/crossfire.cpp +++ b/radio/src/telemetry/crossfire.cpp @@ -198,7 +198,7 @@ void processCrossfireTelemetryFrame() offset /= 10; TRACE("[XF] Rate: %d, Lag: %d", update_interval, offset); - getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset + SAFE_SYNC_LAG); + getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset); } } break; diff --git a/radio/src/telemetry/ghost.cpp b/radio/src/telemetry/ghost.cpp index 2095a3710..1a3cef9d4 100755 --- a/radio/src/telemetry/ghost.cpp +++ b/radio/src/telemetry/ghost.cpp @@ -141,7 +141,7 @@ void processGhostTelemetryFrame() update_interval /= 10; offset /= 10; - getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset + SAFE_SYNC_LAG); + getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset); } break; diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 44906b9d7..03878eee6 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -421,7 +421,7 @@ void ModuleSyncStatus::update(uint16_t newRefreshRate, uint16_t newInputLag) uint16_t ModuleSyncStatus::getAdjustedRefreshRate() { - int16_t lag = currentLag - SAFE_SYNC_LAG; + int16_t lag = currentLag; int32_t newRefreshRate = refreshRate; if (lag == 0) { diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 18f4f98a6..28f66da2c 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -290,8 +290,6 @@ extern Fifo * luaInputTelemetryFifo; void processPXX2Frame(uint8_t module, const uint8_t *frame); // Module pulse synchronization -#define SAFE_SYNC_LAG 800 /* us */ - struct ModuleSyncStatus { // feedback input: last received values From 931743af44b8cc266691776d0c5813db7abdd104 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 15:44:20 +0200 Subject: [PATCH 07/37] init_intmodule_heartbeat --- radio/src/pulses/pulses.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index d21c58853..3fc1868ac 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -411,6 +411,7 @@ static void enablePulsesInternalModule(uint8_t protocol) intmodulePxx1PulsesStart(); #if defined(INTMODULE_HEARTBEAT) // use backup trigger (1 ms later) + init_intmodule_heartbeat(); mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1000/*us*/); #else mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); @@ -423,6 +424,7 @@ static void enablePulsesInternalModule(uint8_t protocol) intmodulePxx1SerialStart(); #if defined(INTMODULE_HEARTBEAT) // use backup trigger (1 ms later) + init_intmodule_heartbeat(); mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1000/*us*/); #else mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); @@ -437,6 +439,7 @@ static void enablePulsesInternalModule(uint8_t protocol) #if defined(INTMODULE_HEARTBEAT) // use backup trigger (1 ms later) + init_intmodule_heartbeat(); mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD + 1000/*us*/); #else mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD); From e00224fea192e133898d887c6c1cf7f325c935b1 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 19:19:23 +0200 Subject: [PATCH 08/37] fix SBUS rate adjustment --- radio/src/pulses/pulses.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 3fc1868ac..f6bb81176 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -333,6 +333,9 @@ bool setupPulsesExternalModule(uint8_t protocol) #if defined(SBUS) case PROTOCOL_CHANNELS_SBUS: setupPulsesSbus(); + + // SBUS_PERIOD is not a constant! It can be set from UI + mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD); return true; #endif From e2fb0522cd8e473457676977b660afc1f00bda7e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 22:33:03 +0200 Subject: [PATCH 09/37] fixed pxx1 driver --- radio/src/pulses/pxx.h | 2 +- .../src/targets/taranis/extmodule_driver.cpp | 32 ++++++++++++------- radio/src/tasks.cpp | 2 ++ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index ae84d77b2..b9536d723 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -108,7 +108,7 @@ class PwmPxxBitTransport: public PulsesBuffer { void addTail() { // rest min value is 18000 - 200 * 48 = 8400 (4.2ms) - *(ptr - 1) += rest; + *(ptr - 1) = 60000;//+= rest; } }; diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 7a7927a41..b8139ad6a 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -98,7 +98,7 @@ void extmoduleSerialStart() GPIO_Init(EXTMODULE_TX_GPIO, &GPIO_InitStructure); EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2 MHz) EXTMODULE_TIMER->CCR3 = 0; EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | EXTMODULE_TIMER_OUTPUT_POLARITY; @@ -215,16 +215,17 @@ void extmodulePxx1PulsesStart() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + + EXTMODULE_TIMER->CCR3 = 0; EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | EXTMODULE_TIMER_OUTPUT_POLARITY; // polarity, default low EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs EXTMODULE_TIMER->CCR1 = 18; EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high EXTMODULE_TIMER->EGR = 1; // Restart - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; - EXTMODULE_TIMER->ARR = 45000; - EXTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // 0 TOGGLE / 2 PWM1 + EXTMODULE_TIMER->ARR = 40000; EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_UDE | TIM_DIER_CC2IE; + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn); @@ -258,13 +259,23 @@ void extmoduleSendNextFrame() #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: - EXTMODULE_TIMER->CCR2 = extmodulePulsesData.pxx.getLast() - 4000; // 2mS in advance + + if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) + return; + + // disable timer + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData()); EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.pxx.getSize(); EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + + // re-init timer + EXTMODULE_TIMER->EGR = 1; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; break; #endif @@ -389,11 +400,10 @@ extern "C" void EXTMODULE_TIMER_DMA_STREAM_IRQHandler() DMA_ClearITPendingBit(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC); switch (moduleState[EXTERNAL_MODULE].protocol) { - case PROTOCOL_CHANNELS_PXX1_PULSES: - case PROTOCOL_CHANNELS_PPM: - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - break; + case PROTOCOL_CHANNELS_PPM: + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + break; } } diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 431ed7e52..8346b2ceb 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -91,6 +91,8 @@ bool isModuleSynchronous(uint8_t moduleIdx) #if defined(INTMODULE_USART) || defined(EXTMODULE_USART) case PROTOCOL_CHANNELS_PXX1_SERIAL: #endif + // case PROTOCOL_CHANNELS_PPM: + case PROTOCOL_CHANNELS_PXX1_PULSES: #if defined(DSM2) case PROTOCOL_CHANNELS_SBUS: case PROTOCOL_CHANNELS_DSM2_LP45: From 47f38dc5b79d35218047d52417704655a143d9ec Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 23:04:43 +0200 Subject: [PATCH 10/37] potential fix for internal PXX1 --- .../taranis/intmodule_pulses_driver.cpp | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index e71768eac..7b8c40578 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -42,21 +42,31 @@ void intmoduleSendNextFrame() #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: { - uint32_t last = intmodulePulsesData.pxx.getLast(); - if (heartbeatCapture.valid) { - if (getTmr2MHz() - heartbeatCapture.timestamp > HEARBEAT_OFFSET) - last -= 21; - else - last += 19; - intmodulePulsesData.pxx.setLast(last); - } - INTMODULE_TIMER->CCR2 = last - 4000; // 2mS in advance + // uint32_t last = intmodulePulsesData.pxx.getLast(); + // if (heartbeatCapture.valid) { + // if (getTmr2MHz() - heartbeatCapture.timestamp > HEARBEAT_OFFSET) + // last -= 21; + // else + // last += 19; + // intmodulePulsesData.pxx.setLast(last); + // } + if (INTMODULE_DMA_STREAM->CR & DMA_SxCR_EN) + return; + + //disable timer + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + + //INTMODULE_TIMER->CCR2 = last - 4000; // 2mS in advance INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR); INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(intmodulePulsesData.pxx.getData()); INTMODULE_DMA_STREAM->NDTR = intmodulePulsesData.pxx.getSize(); INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + + // re-init timer + EXTMODULE_TIMER->EGR = 1; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; break; } #endif @@ -97,17 +107,16 @@ void intmodulePxx1PulsesStart() INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - INTMODULE_TIMER->ARR = 18000; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE; INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs INTMODULE_TIMER->CCR3 = 16; INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; + INTMODULE_TIMER->ARR = 40000; INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->CCR2 = 16000; // The first frame will be sent in 20ms - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn); @@ -157,8 +166,12 @@ extern "C" void INTMODULE_DMA_STREAM_IRQHandler() DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC); - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + switch (moduleState[INTERNAL_MODULE].protocol) { + case PROTOCOL_CHANNELS_PPM: + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + break; + } } extern "C" void INTMODULE_TIMER_CC_IRQHandler() From 02c7d5004ab9e2f007efff05bba1a5ec9a5fbc6b Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 8 Sep 2020 23:04:43 +0200 Subject: [PATCH 11/37] fixed internal PXX1 re-enable for DMA request --- radio/src/targets/taranis/intmodule_pulses_driver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index 7b8c40578..9dad13fd1 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -65,8 +65,8 @@ void intmoduleSendNextFrame() INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA // re-init timer - EXTMODULE_TIMER->EGR = 1; - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + INTMODULE_TIMER->EGR = 1; + INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; break; } #endif From 3f3747c0c75856046d7ede0b53412766a46a2cbc Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 10 Sep 2020 21:00:19 +0200 Subject: [PATCH 12/37] pxx1 internal module: add pre-load register enable (required for pwm mode) --- radio/src/targets/taranis/intmodule_pulses_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index 9dad13fd1..588e1a448 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -113,7 +113,7 @@ void intmodulePxx1PulsesStart() INTMODULE_TIMER->CCR3 = 16; INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE; INTMODULE_TIMER->ARR = 40000; INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update From 3c98a9907eeb12b80b80e0cdf589fcbcd43fb700 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 12 Sep 2020 11:10:36 +0200 Subject: [PATCH 13/37] fixed extmodule serial polarity --- radio/src/targets/taranis/extmodule_driver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index b8139ad6a..4bc47698e 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -321,13 +321,13 @@ void extmoduleSendNextFrame() if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) return; + // disable timer + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + if (PROTOCOL_CHANNELS_SBUS == moduleState[EXTERNAL_MODULE].protocol) { EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // reverse polarity for Sbus if needed } - // disable timer - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - // send DMA request EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; From 87b63402fd2772285868de3f5fc6bc34261e86ae Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 12 Sep 2020 13:19:59 +0200 Subject: [PATCH 14/37] set minimum period to 1750us This should allow 500Hz refresh rate + some headroom for sync. --- radio/src/mixer_scheduler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/mixer_scheduler.h b/radio/src/mixer_scheduler.h index ccded9a5e..601f3fcd7 100644 --- a/radio/src/mixer_scheduler.h +++ b/radio/src/mixer_scheduler.h @@ -23,7 +23,7 @@ #define MIXER_SCHEDULER_DEFAULT_PERIOD_US 4000u // 4ms -#define MIN_REFRESH_RATE 4000 /* us */ +#define MIN_REFRESH_RATE 1750 /* us */ #define MAX_REFRESH_RATE 25000 /* us */ #if !defined(SIMU) From 1c33efac9f6e68fd00989ec7e5cc8966a71c8969 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 12 Sep 2020 21:59:48 +0200 Subject: [PATCH 15/37] fixed AFHDS3 taranis external module --- radio/src/pulses/afhds3.h | 13 +------------ radio/src/targets/taranis/extmodule_driver.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/radio/src/pulses/afhds3.h b/radio/src/pulses/afhds3.h index fab057854..5eef56a4b 100644 --- a/radio/src/pulses/afhds3.h +++ b/radio/src/pulses/afhds3.h @@ -94,9 +94,6 @@ struct Data void reset() { -#if !(defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)) - total = 0; -#endif pulsesSize = 0; } #if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) @@ -118,7 +115,6 @@ struct Data return; } pulses[pulsesSize++] = v; - total += v; } void sendByte(uint8_t b) { @@ -149,14 +145,7 @@ struct Data //add remaining time of frame void flush() { - uint16_t diff = AFHDS3_FRAME_HALF_US - total; - pulses[pulsesSize - 1] += diff; - //ensure 2 ms break - if (pulses[pulsesSize - 1] < 4000) - { - pulses[pulsesSize - 1] = 4050; - } - total += diff; + pulses[pulsesSize - 1] = 60000; } const uint16_t* getData() diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 4bc47698e..b856cb309 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -297,15 +297,21 @@ void extmoduleSendNextFrame() #if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize()); #else + if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) + return; + const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData(); uint32_t dataSize = extmodulePulsesData.afhds3.getSize(); - EXTMODULE_TIMER->CCR2 = dataPtr[dataSize -1] - 4000; // 2mS in advance EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr); EXTMODULE_TIMER_DMA_STREAM->NDTR = dataSize; EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + + // re-init timer + EXTMODULE_TIMER->EGR = TIM_PSCReloadMode_Immediate; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; #endif } break; From 860b50faae0ddc1f603a8a542f21e27659d6294b Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 21 Dec 2020 19:28:05 +0100 Subject: [PATCH 16/37] Improve build files --- tools/boards.py | 69 +++++++++++++++++++++++++++++++++++++++++++++ tools/build-imrc.py | 65 ++++++++++++++++++++++++++++++++++++++++++ tools/build-tbs.py | 57 ++----------------------------------- 3 files changed, 136 insertions(+), 55 deletions(-) create mode 100755 tools/boards.py create mode 100755 tools/build-imrc.py diff --git a/tools/boards.py b/tools/boards.py new file mode 100755 index 000000000..72e367cb3 --- /dev/null +++ b/tools/boards.py @@ -0,0 +1,69 @@ +#!/usr/bin/python3 + +boards = { + "XLITE": { + "PCB": "XLITE", + }, + "XLITES": { + "PCB": "XLITES", + }, + "X9LITE": { + "PCB": "X9LITE", + }, + "X9LITES": { + "PCB": "X9LITES", + }, + "X9D": { + "PCB": "X9D", + }, + "X9D+": { + "PCB": "X9D+", + }, + "X9D+2019": { + "PCB": "X9D+", + "PCBREV": "2019", + }, + "X9E": { + "PCB": "X9E", + }, + "X7": { + "PCB": "X7", + }, + "X7ACCESS": { + "PCB": "X7", + "PCBREV": "ACCESS", + }, + "X10": { + "PCB": "X10", + }, + "X10EXPRESS": { + "PCB": "X10", + "PCBREV": "EXPRESS", + }, + "X12S": { + "PCB": "X12S", + }, + "T16": { + "PCB": "X10", + "PCBREV": "T16", + "INTERNAL_MODULE_MULTI": "YES" + }, + "T18": { + "PCB": "X10", + "PCBREV": "T18", + "INTERNAL_MODULE_MULTI": "YES" + }, + "TX16S": { + "PCB": "X10", + "PCBREV": "TX16S", + "INTERNAL_MODULE_MULTI": "YES" + }, + "T12": { + "PCB": "X7", + "PCBREV": "T12", + }, + "TX12": { + "PCB": "X7", + "PCBREV": "TX12", + }, +} diff --git a/tools/build-imrc.py b/tools/build-imrc.py new file mode 100755 index 000000000..b739a3fc6 --- /dev/null +++ b/tools/build-imrc.py @@ -0,0 +1,65 @@ +#!/usr/bin/python3 + +import argparse +import datetime +import os +from builtins import NotADirectoryError +import shutil +import tempfile + +from boards import * + +translations = [ + "EN" +] + + +def timestamp(): + return datetime.datetime.now().strftime("%Y%m%d") + + +def build(board, translation, srcdir): + cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in boards[board].items()]) + cwd = os.getcwd() + if not os.path.exists("output"): + os.mkdir("output") + path = tempfile.mkdtemp() + os.chdir(path) + command = "cmake %s -DTRANSLATIONS=%s -DIMRC_RELEASE=YES -DGHOST=YES -DTEST_BUILD_WARNING=YES %s" % (cmake_options, translation, srcdir) + print(command) + os.system(command) + os.system("make firmware -j16") + os.chdir(cwd) + index = 0 + while 1: + suffix = "" if index == 0 else "_%d" % index + filename = "output/ghost_firm_%s_%s_%s%s.bin" % (board.lower(), translation.lower(), timestamp(), suffix) + if not os.path.exists(filename): + shutil.copy("%s/firmware.bin" % path, filename) + break + index += 1 + shutil.rmtree(path) + + +def dir_path(string): + if os.path.isdir(string): + return string + else: + raise NotADirectoryError(string) + + +def main(): + parser = argparse.ArgumentParser(description="Build Ghost firmware") + parser.add_argument("-b", "--boards", action="append", help="Destination boards", required=True) + parser.add_argument("-t", "--translations", action="append", help="Translations", required=True) + parser.add_argument("srcdir", type=dir_path) + + args = parser.parse_args() + + for board in (boards.keys() if "ALL" in args.boards else args.boards): + for translation in (translations if "ALL" in args.translations else args.translations): + build(board, translation, args.srcdir) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tools/build-tbs.py b/tools/build-tbs.py index 3c5cb2d1c..a7a0bfc23 100755 --- a/tools/build-tbs.py +++ b/tools/build-tbs.py @@ -7,60 +7,7 @@ from builtins import NotADirectoryError import shutil import tempfile - -boards = { - "XLITE": { - "PCB": "XLITE", - }, - "XLITES": { - "PCB": "XLITES", - }, - "X9LITE": { - "PCB": "X9LITE", - }, - "X9LITES": { - "PCB": "X9LITES", - }, - "X9D": { - "PCB": "X9D+", - }, - "X9D+": { - "PCB": "X9D+", - }, - "X9D+2019": { - "PCB": "X9D+", - "PCBREV": "2019", - }, - "X9E": { - "PCB": "X9E", - }, - "X7": { - "PCB": "X7", - }, - "X7ACCESS": { - "PCB": "X7", - "PCBREV": "ACCESS", - }, - "X10": { - "PCB": "X10", - }, - "X10EXPRESS": { - "PCB": "X10", - "PCBREV": "EXPRESS", - }, - "X12S": { - "PCB": "X12S", - }, - "T16": { - "PCB": "X10", - "PCBREV": "T16", - "INTERNAL_MODULE_MULTI": "YES" - }, - "T12": { - "PCB": "X7", - "PCBREV": "T12", - }, -} +from boards import * translations = [ "EN" @@ -86,7 +33,7 @@ def build(board, translation, srcdir): index = 0 while 1: suffix = "" if index == 0 else "_%d" % index - filename = "output/firmware_%s_%s_%s%s.bin" % (board.lower(), translation.lower(), timestamp(), suffix) + filename = "output/tbs_firm_%s_%s_%s%s.bin" % (board.lower(), translation.lower(), timestamp(), suffix) if not os.path.exists(filename): shutil.copy("%s/firmware.bin" % path, filename) break From e9c9fcda14a08356db7369e452e863d8bbeb9b19 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 22 Dec 2020 08:53:10 +0100 Subject: [PATCH 17/37] Improve build files --- tools/build-tbs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build-tbs.py b/tools/build-tbs.py index a7a0bfc23..729855df0 100755 --- a/tools/build-tbs.py +++ b/tools/build-tbs.py @@ -28,7 +28,7 @@ def build(board, translation, srcdir): command = "cmake %s -DTRANSLATIONS=%s -DTBS_RELEASE=YES -DTEST_BUILD_WARNING=YES %s" % (cmake_options, translation, srcdir) print(command) os.system(command) - os.system("make firmware -j6") + os.system("make firmware -j16") os.chdir(cwd) index = 0 while 1: From d188b50a06f3e569d90403c3d2a39e53f8c052b0 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 20 Dec 2020 09:43:29 +0100 Subject: [PATCH 18/37] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index da2a9413c..aa39c5bd1 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2052,3 +2052,5 @@ Robert Rubio Dennis G Miller Leonardo Garcia Osuna Antonio Carrasco Pastor +Musa Pinar +Jens Moder From 78b86e61d5eb38972130260408de82fc76594334 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 20 Dec 2020 19:28:57 +0100 Subject: [PATCH 19/37] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index aa39c5bd1..8d764caac 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2054,3 +2054,4 @@ Leonardo Garcia Osuna Antonio Carrasco Pastor Musa Pinar Jens Moder +Josef de Beer From f3ffdbff0a76365ed1c310e4ac51abd48ffdfad4 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 21 Dec 2020 12:14:18 +0100 Subject: [PATCH 20/37] Fix hardcoded string --- radio/src/gui/480x272/view_about.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/480x272/view_about.cpp b/radio/src/gui/480x272/view_about.cpp index 3f5e14660..ea3561188 100644 --- a/radio/src/gui/480x272/view_about.cpp +++ b/radio/src/gui/480x272/view_about.cpp @@ -128,7 +128,7 @@ bool menuAboutView(event_t event) break; case ABOUT_HARDWARE: - lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, "FrSky", INVERS); + lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_HARDWARE_1, INVERS); lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_HARDWARE_2); lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_HARDWARE_3); break; From d712a17f62f9e337cef178da5fba1449995cf6e1 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 22 Dec 2020 10:07:37 +0100 Subject: [PATCH 21/37] Handle more module combination --- radio/src/mixer_scheduler.cpp | 7 +++++-- radio/src/tasks.cpp | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp index b29c821c8..82dfb7086 100644 --- a/radio/src/mixer_scheduler.cpp +++ b/radio/src/mixer_scheduler.cpp @@ -37,13 +37,16 @@ static MixerSchedule mixerSchedules[NUM_MODULES]; uint16_t getMixerSchedulerPeriod() { +#if defined(INTERNAL_MODULE) if (mixerSchedules[INTERNAL_MODULE].period) { return mixerSchedules[INTERNAL_MODULE].period; } - else if (mixerSchedules[EXTERNAL_MODULE].period) { +#endif +#if defined(EXTERNAL_MODULE) + if (mixerSchedules[EXTERNAL_MODULE].period) { return mixerSchedules[EXTERNAL_MODULE].period; } - +#endif return MIXER_SCHEDULER_DEFAULT_PERIOD_US; } diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 8346b2ceb..f85c6a6b2 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -174,7 +174,14 @@ TASK_FUNCTION(mixerTask) doMixerCalculations(); // TODO: fix runMask - sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE)); + uint8_t runMask = 0; +#if defined(INTERNAL_MODULE) + runMask != (1 << INTERNAL_MODULE) +#endif +#if defined(EXTERNAL_MODULE) + runMask != (1 << EXTERNAL_MODULE) +#endif + sendSynchronousPulses(runMask); doMixerPeriodicUpdates(); From 803701bfb26d62356a1e125b02eec8f325508661 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 20 Dec 2020 09:43:29 +0100 Subject: [PATCH 22/37] Update CREDITS.txt --- CREDITS.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CREDITS.txt b/CREDITS.txt index 8d764caac..aa39c5bd1 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2054,4 +2054,3 @@ Leonardo Garcia Osuna Antonio Carrasco Pastor Musa Pinar Jens Moder -Josef de Beer From a6617d621fb141944a808f0745d0163790c35b71 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 20 Dec 2020 19:28:57 +0100 Subject: [PATCH 23/37] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index aa39c5bd1..8d764caac 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2054,3 +2054,4 @@ Leonardo Garcia Osuna Antonio Carrasco Pastor Musa Pinar Jens Moder +Josef de Beer From 70c1d77648faf107aceb3a063e5c442aaa494ee0 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 23 Dec 2020 20:24:20 +0100 Subject: [PATCH 24/37] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 8d764caac..10e2bb105 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2055,3 +2055,4 @@ Antonio Carrasco Pastor Musa Pinar Jens Moder Josef de Beer +Chad Mofford From e64c292d73056a98765dbfc7f7b90eaf58ef7048 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 25 Dec 2020 18:55:26 +0100 Subject: [PATCH 25/37] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 10e2bb105..174d95b34 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2056,3 +2056,4 @@ Musa Pinar Jens Moder Josef de Beer Chad Mofford +Pim Pouw From 6daeb7477f3974200f24470752dacec935d640de Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 28 Dec 2020 11:31:11 +0100 Subject: [PATCH 26/37] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 174d95b34..e229ec8e1 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2057,3 +2057,4 @@ Jens Moder Josef de Beer Chad Mofford Pim Pouw +Kenth Jonsson From 749e8c547d9d5c6b1112590d5ed2385194059cc1 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 29 Dec 2020 16:07:10 +0100 Subject: [PATCH 27/37] Fix multi telemetry not working when CRSF or Ghost had been selected --- radio/src/telemetry/telemetry.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 03878eee6..5c5b1181c 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -291,6 +291,7 @@ void telemetryInit(uint8_t protocol) #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 From d583f7536c2bc11d41399f0f46f3bdb07e67bf39 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 29 Dec 2020 16:31:13 +0100 Subject: [PATCH 28/37] Fix compilation --- radio/src/targets/sky9x/board.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h index 2d098a45f..0a6aef20d 100644 --- a/radio/src/targets/sky9x/board.h +++ b/radio/src/targets/sky9x/board.h @@ -398,6 +398,9 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode); inline void telemetryPortSetDirectionOutput() { } +inline void telemetryPortSetDirectionInput() +{ +} uint32_t telemetryTransmitPending(); void telemetryTransmitBuffer(const uint8_t * buffer, uint32_t size); void rxPdcUsart( void (*pChProcess)(uint8_t x) ); From 31c20fc8eba55359e1af92f0650374f67c35c5cd Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 8 Jan 2021 17:53:38 +0100 Subject: [PATCH 29/37] Fix synced --- radio/src/mixer_scheduler.cpp | 4 ++-- radio/src/tasks.cpp | 9 +-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp index 82dfb7086..8132fe2f0 100644 --- a/radio/src/mixer_scheduler.cpp +++ b/radio/src/mixer_scheduler.cpp @@ -37,12 +37,12 @@ static MixerSchedule mixerSchedules[NUM_MODULES]; uint16_t getMixerSchedulerPeriod() { -#if defined(INTERNAL_MODULE) +#if defined(HARDWARE_INTERNAL_MODULE) if (mixerSchedules[INTERNAL_MODULE].period) { return mixerSchedules[INTERNAL_MODULE].period; } #endif -#if defined(EXTERNAL_MODULE) +#if 1 //defined(HARDWARE_EXTERNAL_MODULE) if (mixerSchedules[EXTERNAL_MODULE].period) { return mixerSchedules[EXTERNAL_MODULE].period; } diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index f85c6a6b2..8346b2ceb 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -174,14 +174,7 @@ TASK_FUNCTION(mixerTask) doMixerCalculations(); // TODO: fix runMask - uint8_t runMask = 0; -#if defined(INTERNAL_MODULE) - runMask != (1 << INTERNAL_MODULE) -#endif -#if defined(EXTERNAL_MODULE) - runMask != (1 << EXTERNAL_MODULE) -#endif - sendSynchronousPulses(runMask); + sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE)); doMixerPeriodicUpdates(); From 87c9cfa610da2db7480bb9ba5a2b6dce51f75080 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 10 Jan 2021 08:23:48 +0100 Subject: [PATCH 30/37] Update --- tools/build-imrc.py | 2 +- tools/build-tbs.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/build-imrc.py b/tools/build-imrc.py index b739a3fc6..e0c8cf061 100755 --- a/tools/build-imrc.py +++ b/tools/build-imrc.py @@ -25,7 +25,7 @@ def build(board, translation, srcdir): os.mkdir("output") path = tempfile.mkdtemp() os.chdir(path) - command = "cmake %s -DTRANSLATIONS=%s -DIMRC_RELEASE=YES -DGHOST=YES -DTEST_BUILD_WARNING=YES %s" % (cmake_options, translation, srcdir) + command = "cmake %s -DTRANSLATIONS=%s -DIMRC_RELEASE=YES -DGHOST=YES %s" % (cmake_options, translation, srcdir) print(command) os.system(command) os.system("make firmware -j16") diff --git a/tools/build-tbs.py b/tools/build-tbs.py index 729855df0..4d469c608 100755 --- a/tools/build-tbs.py +++ b/tools/build-tbs.py @@ -25,7 +25,7 @@ def build(board, translation, srcdir): os.mkdir("output") path = tempfile.mkdtemp() os.chdir(path) - command = "cmake %s -DTRANSLATIONS=%s -DTBS_RELEASE=YES -DTEST_BUILD_WARNING=YES %s" % (cmake_options, translation, srcdir) + command = "cmake %s -DTRANSLATIONS=%s -DTBS_RELEASE=YES %s" % (cmake_options, translation, srcdir) print(command) os.system(command) os.system("make firmware -j16") From 99ff3f9f8c37a63b0f787123845ad57eb8c35c49 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 10 Jan 2021 09:35:44 +0100 Subject: [PATCH 31/37] Add 'synced' to firmware options display --- radio/src/options.h | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/options.h b/radio/src/options.h index acadfd129..bc50f70fd 100644 --- a/radio/src/options.h +++ b/radio/src/options.h @@ -23,6 +23,7 @@ #define OPENTX_OPTIONS_H static const char * const options[] = { + "synced", #if defined(AUTOUPDATE) "autoupdate", #endif From e1e097d4294a3ce4e478d4ec4ef487caf48197e0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 26 Jan 2021 11:50:47 +0100 Subject: [PATCH 32/37] Disable commit-tests for AR9X, 9XPRO and SKY9X in synced branch for now --- tools/commit-tests.sh | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index be5940308..9ecd88769 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -58,32 +58,32 @@ COMMON_OPTIONS+=${EXTRA_OPTIONS} mkdir build || true cd build -if [[ " SKY9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then - # OpenTX on Sky9x - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=SKY9X -DHELI=YES DLUA=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES -DGVARS=YES "${SRCDIR}" - make -j"${CORES}" ${FIRMARE_TARGET} - make -j"${CORES}" libsimulator - make -j"${CORES}" tests-radio -fi - -if [[ " AR9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then - # OpenTX on AR9X - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=AR9X -DHELI=YES -DGVARS=YES "${SRCDIR}" - make -j"${CORES}" ${FIRMARE_TARGET} - make -j"${CORES}" libsimulator - make -j"${CORES}" tests-radio -fi - -if [[ " 9XRPRO ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then - # OpenTX on Sky9x - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=9XRPRO -DHELI=YES -DGVARS=YES "${SRCDIR}" - make -j"${CORES}" ${FIRMARE_TARGET} - make -j"${CORES}" libsimulator - make -j"${CORES}" tests-radio -fi +#if [[ " SKY9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then +# # OpenTX on Sky9x +# rm -rf ./* +# cmake "${COMMON_OPTIONS}" -DPCB=SKY9X -DHELI=YES DLUA=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES -DGVARS=YES "${SRCDIR}" +# make -j"${CORES}" ${FIRMARE_TARGET} +# make -j"${CORES}" libsimulator +# make -j"${CORES}" tests-radio +#fi +# +#if [[ " AR9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then +# # OpenTX on AR9X +# rm -rf ./* +# cmake "${COMMON_OPTIONS}" -DPCB=AR9X -DHELI=YES -DGVARS=YES "${SRCDIR}" +# make -j"${CORES}" ${FIRMARE_TARGET} +# make -j"${CORES}" libsimulator +# make -j"${CORES}" tests-radio +#fi +# +#if [[ " 9XRPRO ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then +# # OpenTX on Sky9x +# rm -rf ./* +# cmake "${COMMON_OPTIONS}" -DPCB=9XRPRO -DHELI=YES -DGVARS=YES "${SRCDIR}" +# make -j"${CORES}" ${FIRMARE_TARGET} +# make -j"${CORES}" libsimulator +# make -j"${CORES}" tests-radio +#fi if [[ " X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITE From 78dd516069c7055bc27e5013b1565d985baea69b Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 4 Apr 2021 19:00:01 +0200 Subject: [PATCH 33/37] Allow PCBSKY9X compilation --- radio/src/opentx.h | 1 + radio/src/pulses/pulses.cpp | 43 ++++++++++++++++++++++++++++++++++- radio/src/tasks.cpp | 28 +++++++++++++++++++++++ radio/src/telemetry/multi.cpp | 3 ++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 3d3cc3ae7..ddfcb9830 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -502,6 +502,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms); void evalMixes(uint8_t tick10ms); void doMixerCalculations(); void doMixerPeriodicUpdates(); +void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms); void checkTrims(); extern uint8_t currentBacklightBright; diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 7292bb200..810fd9378 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -241,8 +241,12 @@ void enablePulsesExternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_DSM2_LP45: case PROTOCOL_CHANNELS_DSM2_DSM2: case PROTOCOL_CHANNELS_DSM2_DSMX: +#if defined(PCBSKY9X) + extmoduleSerialStart(DSM2_BAUDRATE, DSM2_PERIOD * 2000, false); +#else extmoduleSerialStart(); mixerSchedulerSetPeriod(EXTERNAL_MODULE, DSM2_PERIOD); +#endif break; #endif @@ -274,15 +278,23 @@ void enablePulsesExternalModule(uint8_t protocol) #if defined(MULTIMODULE) case PROTOCOL_CHANNELS_MULTIMODULE: +#if defined(PCBSKY9X) + extmoduleSerialStart(MULTIMODULE_BAUDRATE, MULTIMODULE_PERIOD * 2000, true); +#else extmoduleSerialStart(); mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD); +#endif break; #endif #if defined(SBUS) case PROTOCOL_CHANNELS_SBUS: +#if defined(PCBSKY9X) + extmoduleSerialStart(SBUS_BAUDRATE, SBUS_PERIOD_HALF_US, false); +#else extmoduleSerialStart(); mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD); +#endif break; #endif @@ -314,12 +326,18 @@ bool setupPulsesExternalModule(uint8_t protocol) #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: extmodulePulsesData.pxx.setupFrame(EXTERNAL_MODULE); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX_PULSES_PERIOD); +#endif return true; #endif #if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) case PROTOCOL_CHANNELS_PXX1_SERIAL: extmodulePulsesData.pxx_uart.setupFrame(EXTERNAL_MODULE); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, EXTMODULE_PXX1_SERIAL_PERIOD); +#endif return true; #endif @@ -327,13 +345,18 @@ bool setupPulsesExternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: case PROTOCOL_CHANNELS_PXX2_LOWSPEED: extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE); +#if defined(PCBSKY9X) + sheduleNextMixerCalculation(EXTERNAL_MODULE, PXX2_PERIOD); +#endif return true; #endif #if defined(SBUS) case PROTOCOL_CHANNELS_SBUS: setupPulsesSbus(); - +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, SBUS_PERIOD); +#endif // SBUS_PERIOD is not a constant! It can be set from UI mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD); return true; @@ -344,6 +367,9 @@ bool setupPulsesExternalModule(uint8_t protocol) case PROTOCOL_CHANNELS_DSM2_DSM2: case PROTOCOL_CHANNELS_DSM2_DSMX: setupPulsesDSM2(); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, DSM2_PERIOD); +#endif return true; #endif @@ -356,6 +382,9 @@ bool setupPulsesExternalModule(uint8_t protocol) else mixerSchedulerSetPeriod(EXTERNAL_MODULE, CROSSFIRE_PERIOD); setupPulsesCrossfire(); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, CROSSFIRE_PERIOD); +#endif return true; } #endif @@ -369,6 +398,9 @@ bool setupPulsesExternalModule(uint8_t protocol) else mixerSchedulerSetPeriod(EXTERNAL_MODULE, GHOST_PERIOD); setupPulsesGhost(); +#if defined(PCBSKPCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, GHOST_PERIOD); +#endif return true; } #endif @@ -382,6 +414,9 @@ bool setupPulsesExternalModule(uint8_t protocol) else mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD); setupPulsesMultiExternalModule(); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, MULTIMODULE_PERIOD); +#endif return true; } #endif @@ -389,12 +424,18 @@ bool setupPulsesExternalModule(uint8_t protocol) #if defined(PPM) case PROTOCOL_CHANNELS_PPM: setupPulsesPPMExternalModule(); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE)); +#endif return true; #endif #if defined(AFHDS3) case PROTOCOL_CHANNELS_AFHDS3: extmodulePulsesData.afhds3.setupFrame(); +#if defined(PCBSKY9X) + scheduleNextMixerCalculation(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT); +#endif return true; #endif diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index d0aa8e3d2..97f78c972 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -118,7 +118,9 @@ TASK_FUNCTION(mixerTask) s_pulses_paused = true; mixerSchedulerInit(); +#if !defined(PCBSKY9X) mixerSchedulerStart(); +#endif while (true) { #if defined(SBUS_TRAINER) @@ -142,8 +144,10 @@ TASK_FUNCTION(mixerTask) GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); #endif +#if !defined(PCBSKY9X) // re-enable trigger mixerSchedulerEnableTrigger(); +#endif #if defined(SIMU) if (pwrCheck() == e_power_off) { @@ -164,7 +168,11 @@ TASK_FUNCTION(mixerTask) doMixerCalculations(); // TODO: fix runMask +#if defined(PCBSKY9X) + sendSynchronousPulses(1 << EXTERNAL_MODULE); +#else sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE)); +#endif doMixerPeriodicUpdates(); @@ -200,12 +208,32 @@ TASK_FUNCTION(mixerTask) // TODO: // - check the cause of timeouts when switching // between protocols with multi-proto RF +#if defined(DEBUG) if (timeout) serialPrint("mix sched timeout!"); +#endif } } } +void scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms) +{ + // Schedule next mixer calculation time, + + if (isModuleSynchronous(module)) { + nextMixerTime[module] += period_ms / RTOS_MS_PER_TICK; + if (nextMixerTime[module] < RTOS_GET_TIME()) { + // we are late ... let's add some small delay + nextMixerTime[module] = (uint32_t) RTOS_GET_TIME() + (period_ms / RTOS_MS_PER_TICK); + } + } + else { + // for now assume mixer calculation takes 2 ms. + nextMixerTime[module] = (uint32_t) RTOS_GET_TIME() + (period_ms / RTOS_MS_PER_TICK); + } + + DEBUG_TIMER_STOP(debugTimerMixerCalcToUsage); +} #define MENU_TASK_PERIOD_TICKS (50 / RTOS_MS_PER_TICK) // 50ms diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 1cb560b14..624effbba 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -252,8 +252,9 @@ static void processMultiSyncPacket(const uint8_t * data, uint8_t module) // inputLag -= refreshRate; status.update(refreshRate, inputLag); - +#if defined(DEBUG) serialPrint("MP ADJ: R %d, L %04d", refreshRate, inputLag); +#endif } #if defined(PCBTARANIS) || defined(PCBHORUS) From 84387e7e0f99169fdf88247b4f819954505d29e6 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 5 Apr 2021 11:16:17 +0200 Subject: [PATCH 34/37] Cosmetics --- radio/src/gui/gui_common.h | 1 - .../taranis/intmodule_pulses_driver.cpp | 8 --- radio/src/tasks.cpp | 4 -- radio/src/telemetry/crossfire.cpp | 1 - radio/src/telemetry/crossfire.h | 2 +- radio/src/telemetry/multi.cpp | 3 -- radio/src/telemetry/telemetry.cpp | 4 -- tools/commit-tests.sh | 52 +++++++++---------- 8 files changed, 27 insertions(+), 48 deletions(-) diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index b7d73d075..80b675b42 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -185,7 +185,6 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) } #if defined(MULTIMODULE) - inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx) { if (!isModuleMultimodule(moduleIdx)) diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index 588e1a448..5de2daa1b 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -42,14 +42,6 @@ void intmoduleSendNextFrame() #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: { - // uint32_t last = intmodulePulsesData.pxx.getLast(); - // if (heartbeatCapture.valid) { - // if (getTmr2MHz() - heartbeatCapture.timestamp > HEARBEAT_OFFSET) - // last -= 21; - // else - // last += 19; - // intmodulePulsesData.pxx.setLast(last); - // } if (INTMODULE_DMA_STREAM->CR & DMA_SxCR_EN) return; diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 97f78c972..e71d8829a 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -67,7 +67,6 @@ bool isForcePowerOffRequested() bool isModuleSynchronous(uint8_t moduleIdx) { switch(moduleState[moduleIdx].protocol) { - case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: case PROTOCOL_CHANNELS_PXX2_LOWSPEED: case PROTOCOL_CHANNELS_CROSSFIRE: @@ -109,8 +108,6 @@ void sendSynchronousPulses(uint8_t runMask) } } -//#define DEBUG_MIXER_SCHEDULER - uint32_t nextMixerTime[NUM_MODULES]; TASK_FUNCTION(mixerTask) @@ -181,7 +178,6 @@ TASK_FUNCTION(mixerTask) RTOS_UNLOCK_MUTEX(mixerMutex); DEBUG_TIMER_STOP(debugTimerMixer); - #if defined(STM32) && !defined(SIMU) if (getSelectedUsbMode() == USB_JOYSTICK_MODE) { usbJoystickUpdate(); diff --git a/radio/src/telemetry/crossfire.cpp b/radio/src/telemetry/crossfire.cpp index 173ea38f4..64dba983d 100644 --- a/radio/src/telemetry/crossfire.cpp +++ b/radio/src/telemetry/crossfire.cpp @@ -203,7 +203,6 @@ void processCrossfireTelemetryFrame() } break; - #if defined(LUA) default: if (luaInputTelemetryFifo && luaInputTelemetryFifo->hasSpace(telemetryRxBufferCount-2) ) { diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h index fb68b8a1a..23d39947e 100644 --- a/radio/src/telemetry/crossfire.h +++ b/radio/src/telemetry/crossfire.h @@ -104,7 +104,7 @@ const uint8_t CROSSFIRE_PERIODS[] = { }; #if SPORT_MAX_BAUDRATE < 400000 || defined(DEBUG) #define CROSSFIRE_BAUDRATE CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate] -#define CROSSFIRE_PERIOD (CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate]*1000) +#define CROSSFIRE_PERIOD (CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate] * 1000) #else #define CROSSFIRE_BAUDRATE 400000 #define CROSSFIRE_PERIOD 4000 /* us; 250 Hz */ diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 624effbba..d71cdad34 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -248,9 +248,6 @@ static void processMultiSyncPacket(const uint8_t * data, uint8_t module) uint16_t refreshRate = data[0] << 8 | data[1]; int16_t inputLag = data[2] << 8 | data[3]; - // if (inputLag > refreshRate/2) - // inputLag -= refreshRate; - status.update(refreshRate, inputLag); #if defined(DEBUG) serialPrint("MP ADJ: R %d, L %04d", refreshRate, inputLag); diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 17777dc6a..700bf535a 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -378,23 +378,19 @@ Fifo * luaInputTelemetryFifo = NULL; #endif #if defined(HARDWARE_INTERNAL_MODULE) - static ModuleSyncStatus moduleSyncStatus[NUM_MODULES]; ModuleSyncStatus &getModuleSyncStatus(uint8_t moduleIdx) { return moduleSyncStatus[moduleIdx]; } - #else - static ModuleSyncStatus moduleSyncStatus; ModuleSyncStatus &getModuleSyncStatus(uint8_t moduleIdx) { return moduleSyncStatus; } - #endif ModuleSyncStatus::ModuleSyncStatus() diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 9ecd88769..be5940308 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -58,32 +58,32 @@ COMMON_OPTIONS+=${EXTRA_OPTIONS} mkdir build || true cd build -#if [[ " SKY9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then -# # OpenTX on Sky9x -# rm -rf ./* -# cmake "${COMMON_OPTIONS}" -DPCB=SKY9X -DHELI=YES DLUA=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES -DGVARS=YES "${SRCDIR}" -# make -j"${CORES}" ${FIRMARE_TARGET} -# make -j"${CORES}" libsimulator -# make -j"${CORES}" tests-radio -#fi -# -#if [[ " AR9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then -# # OpenTX on AR9X -# rm -rf ./* -# cmake "${COMMON_OPTIONS}" -DPCB=AR9X -DHELI=YES -DGVARS=YES "${SRCDIR}" -# make -j"${CORES}" ${FIRMARE_TARGET} -# make -j"${CORES}" libsimulator -# make -j"${CORES}" tests-radio -#fi -# -#if [[ " 9XRPRO ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then -# # OpenTX on Sky9x -# rm -rf ./* -# cmake "${COMMON_OPTIONS}" -DPCB=9XRPRO -DHELI=YES -DGVARS=YES "${SRCDIR}" -# make -j"${CORES}" ${FIRMARE_TARGET} -# make -j"${CORES}" libsimulator -# make -j"${CORES}" tests-radio -#fi +if [[ " SKY9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then + # OpenTX on Sky9x + rm -rf ./* + cmake "${COMMON_OPTIONS}" -DPCB=SKY9X -DHELI=YES DLUA=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES -DGVARS=YES "${SRCDIR}" + make -j"${CORES}" ${FIRMARE_TARGET} + make -j"${CORES}" libsimulator + make -j"${CORES}" tests-radio +fi + +if [[ " AR9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then + # OpenTX on AR9X + rm -rf ./* + cmake "${COMMON_OPTIONS}" -DPCB=AR9X -DHELI=YES -DGVARS=YES "${SRCDIR}" + make -j"${CORES}" ${FIRMARE_TARGET} + make -j"${CORES}" libsimulator + make -j"${CORES}" tests-radio +fi + +if [[ " 9XRPRO ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then + # OpenTX on Sky9x + rm -rf ./* + cmake "${COMMON_OPTIONS}" -DPCB=9XRPRO -DHELI=YES -DGVARS=YES "${SRCDIR}" + make -j"${CORES}" ${FIRMARE_TARGET} + make -j"${CORES}" libsimulator + make -j"${CORES}" tests-radio +fi if [[ " X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITE From cff8109d5a15f10ea7b2530d0eb3964db6b6109c Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 5 Apr 2021 17:38:10 +0200 Subject: [PATCH 35/37] Cosmetics --- radio/src/mixer_scheduler.cpp | 6 +++--- radio/src/options.h | 1 - radio/src/pulses/pulses.cpp | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp index 8132fe2f0..dcf95383b 100644 --- a/radio/src/mixer_scheduler.cpp +++ b/radio/src/mixer_scheduler.cpp @@ -42,7 +42,7 @@ uint16_t getMixerSchedulerPeriod() return mixerSchedules[INTERNAL_MODULE].period; } #endif -#if 1 //defined(HARDWARE_EXTERNAL_MODULE) +#if defined(HARDWARE_EXTERNAL_MODULE) if (mixerSchedules[EXTERNAL_MODULE].period) { return mixerSchedules[EXTERNAL_MODULE].period; } @@ -58,10 +58,10 @@ void mixerSchedulerInit() void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs) { - if ((periodUs > 0) && (periodUs < MIN_REFRESH_RATE)) { + if (periodUs > 0 && periodUs < MIN_REFRESH_RATE) { periodUs = MIN_REFRESH_RATE; } - else if ((periodUs > 0) && (periodUs > MAX_REFRESH_RATE)) { + else if (periodUs > 0 && periodUs > MAX_REFRESH_RATE) { periodUs = MAX_REFRESH_RATE; } diff --git a/radio/src/options.h b/radio/src/options.h index 8592897af..4f1a1a077 100644 --- a/radio/src/options.h +++ b/radio/src/options.h @@ -23,7 +23,6 @@ #define OPENTX_OPTIONS_H static const char * const options[] = { - "synced", #if defined(AUTOUPDATE) "autoupdate", #endif diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 810fd9378..128e11976 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -356,11 +356,12 @@ bool setupPulsesExternalModule(uint8_t protocol) setupPulsesSbus(); #if defined(PCBSKY9X) scheduleNextMixerCalculation(EXTERNAL_MODULE, SBUS_PERIOD); -#endif +#else // SBUS_PERIOD is not a constant! It can be set from UI mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD); return true; #endif +#endif #if defined(DSM2) case PROTOCOL_CHANNELS_DSM2_LP45: From 92fb19d89c2775a464bf0f0a71c0fbfc519796a2 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 5 Apr 2021 17:40:55 +0200 Subject: [PATCH 36/37] Cosmetics --- radio/src/pulses/pxx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index b9536d723..e852de180 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -108,7 +108,7 @@ class PwmPxxBitTransport: public PulsesBuffer { void addTail() { // rest min value is 18000 - 200 * 48 = 8400 (4.2ms) - *(ptr - 1) = 60000;//+= rest; + *(ptr - 1) = 60000; } }; From 9ba3914ec464b600ef34381e3a950e99d53e9c25 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 5 Apr 2021 17:51:13 +0200 Subject: [PATCH 37/37] Cosmetics --- radio/src/targets/taranis/extmodule_driver.cpp | 8 ++++---- radio/src/tasks.cpp | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index b856cb309..512f16c5d 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -406,10 +406,10 @@ extern "C" void EXTMODULE_TIMER_DMA_STREAM_IRQHandler() DMA_ClearITPendingBit(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC); switch (moduleState[EXTERNAL_MODULE].protocol) { - case PROTOCOL_CHANNELS_PPM: - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - break; + case PROTOCOL_CHANNELS_PPM: + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + break; } } diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index e71d8829a..a051cc509 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -164,7 +164,6 @@ TASK_FUNCTION(mixerTask) doMixerCalculations(); - // TODO: fix runMask #if defined(PCBSKY9X) sendSynchronousPulses(1 << EXTERNAL_MODULE); #else