1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-14 11:59:50 +03:00

PXX synchro using Hearbeat (#6482)

* [PXX] Latency using heartbeat sync optimized for X7 (stable @ 12ms)
* [PXX] Latency using heartbeat sync optimized for XLite Pro (stable @ 9ms)
This commit is contained in:
Bertrand Songis 2019-06-08 10:44:31 +02:00 committed by GitHub
parent 56a31f20d3
commit aff6c3fd1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 383 additions and 189 deletions

View file

@ -548,9 +548,14 @@ enum SwitchSources {
SWSRC_LAST_FLIGHT_MODE = SWSRC_FIRST_FLIGHT_MODE+MAX_FLIGHT_MODES-1, SWSRC_LAST_FLIGHT_MODE = SWSRC_FIRST_FLIGHT_MODE+MAX_FLIGHT_MODES-1,
SWSRC_TELEMETRY_STREAMING, SWSRC_TELEMETRY_STREAMING,
SWSRC_FIRST_SENSOR, SWSRC_FIRST_SENSOR,
SWSRC_LAST_SENSOR = SWSRC_FIRST_SENSOR+MAX_TELEMETRY_SENSORS-1, SWSRC_LAST_SENSOR = SWSRC_FIRST_SENSOR+MAX_TELEMETRY_SENSORS-1,
#if defined(DEBUG_LATENCY)
SWSRC_LATENCY_TOGGLE,
#endif
SWSRC_COUNT, SWSRC_COUNT,
SWSRC_OFF = -SWSRC_ON, SWSRC_OFF = -SWSRC_ON,

View file

@ -530,7 +530,6 @@ void menuMainView(event_t event)
#endif #endif
} }
else { else {
// Logical Switches // Logical Switches
uint8_t index = 0; uint8_t index = 0;
uint8_t y = LCD_H-20; uint8_t y = LCD_H-20;
@ -552,7 +551,7 @@ void menuMainView(event_t event)
} }
// And ! in case of unexpected shutdown // And ! in case of unexpected shutdown
#if defined(LOG_TELEMETRY) || defined(WATCHDOG_DISABLED) #if defined(LOG_TELEMETRY) || defined(WATCHDOG_DISABLED) || defined(DEBUG_LATENCY)
lcdDrawChar(REBOOT_X, 0*FH, '!', INVERS); lcdDrawChar(REBOOT_X, 0*FH, '!', INVERS);
#else #else
if (unexpectedShutdown) { if (unexpectedShutdown) {

View file

@ -100,19 +100,8 @@ void menuStatisticsView(event_t event)
#endif #endif
} }
#define MENU_DEBUG_COL1_OFS (11*FW-3) #define MENU_DEBUG_COL1_OFS (11*FW-3)
#define MENU_DEBUG_COL2_OFS (17*FW) #define MENU_DEBUG_COL2_OFS (17*FW)
#define MENU_DEBUG_Y_CURRENT (1*FH)
#define MENU_DEBUG_ROW1 (1*FH+1)
#define MENU_DEBUG_ROW2 (2*FH+1)
#define MENU_DEBUG_Y_MAH (2*FH)
#define MENU_DEBUG_Y_CPU_TEMP (3*FH)
#define MENU_DEBUG_Y_COPROC (4*FH)
#define MENU_DEBUG_Y_MIXMAX (5*FH)
#define MENU_DEBUG_Y_RTOS (6*FH)
#define MENU_DEBUG_Y_USB (2*FH)
#define MENU_DEBUG_Y_LUA (3*FH)
#define MENU_DEBUG_Y_FREE_RAM (4*FH)
void menuStatisticsDebug(event_t event) void menuStatisticsDebug(event_t event)
{ {
@ -134,7 +123,6 @@ void menuStatisticsDebug(event_t event)
maxMixerDuration = 0; maxMixerDuration = 0;
break; break;
case EVT_KEY_FIRST(KEY_UP): case EVT_KEY_FIRST(KEY_UP):
#if defined(NAVIGATION_X7) #if defined(NAVIGATION_X7)
case EVT_KEY_BREAK(KEY_PAGE): case EVT_KEY_BREAK(KEY_PAGE):
@ -157,83 +145,105 @@ void menuStatisticsDebug(event_t event)
#if defined(PCBSKY9X) #if defined(PCBSKY9X)
if ((ResetReason&RSTC_SR_RSTTYP) == (2<<8)) { if ((ResetReason&RSTC_SR_RSTTYP) == (2<<8)) {
lcdDrawText(LCD_W-8*FW, 0*FH, "WATCHDOG"); lcdDrawText(LCD_W-8*FW, 0, "WATCHDOG");
} }
else if (unexpectedShutdown) { else if (unexpectedShutdown) {
lcdDrawText(LCD_W-13*FW, 0*FH, "UNEXP.SHTDOWN"); lcdDrawText(LCD_W-13*FW, 0, "UNEXP.SHTDOWN");
} }
#endif #endif
uint8_t y = FH + 1;
#if defined(TX_CAPACITY_MEASUREMENT) #if defined(TX_CAPACITY_MEASUREMENT)
// current // current
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_CURRENT, STR_CPU_CURRENT); lcdDrawTextAlignedLeft(y, STR_CPU_CURRENT);
drawValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CURRENT, getCurrent(), UNIT_MILLIAMPS, LEFT); drawValueWithUnit(MENU_DEBUG_COL1_OFS, y, getCurrent(), UNIT_MILLIAMPS, LEFT);
uint32_t current_scale = 488 + g_eeGeneral.txCurrentCalibration; uint32_t current_scale = 488 + g_eeGeneral.txCurrentCalibration;
lcdDrawChar(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CURRENT, '>'); lcdDrawChar(MENU_DEBUG_COL2_OFS, y, '>');
drawValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CURRENT, Current_max*10*current_scale/8192, UNIT_RAW, LEFT); drawValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, y, Current_max*10*current_scale/8192, UNIT_RAW, LEFT);
y += FH;
// consumption // consumption
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_MAH, STR_CPU_MAH); lcdDrawTextAlignedLeft(y, STR_CPU_MAH);
drawValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MAH, g_eeGeneral.mAhUsed + Current_used*current_scale/8192/36, UNIT_MAH, LEFT|PREC1); drawValueWithUnit(MENU_DEBUG_COL1_OFS, y, g_eeGeneral.mAhUsed + Current_used*current_scale/8192/36, UNIT_MAH, LEFT|PREC1);
y += FH;
#endif #endif
#if defined(PCBSKY9X) #if defined(PCBSKY9X)
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_CPU_TEMP, STR_CPU_TEMP); lcdDrawTextAlignedLeft(y, STR_CPU_TEMP);
drawValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CPU_TEMP, getTemperature(), UNIT_TEMPERATURE, LEFT); drawValueWithUnit(MENU_DEBUG_COL1_OFS, y, getTemperature(), UNIT_TEMPERATURE, LEFT);
lcdDrawChar(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CPU_TEMP, '>'); lcdDrawChar(MENU_DEBUG_COL2_OFS, y, '>');
drawValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CPU_TEMP, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_TEMPERATURE, LEFT); drawValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, y, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_TEMPERATURE, LEFT);
y += FH;
#endif #endif
#if defined(COPROCESSOR) #if defined(COPROCESSOR)
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_COPROC, STR_COPROC_TEMP); lcdDrawTextAlignedLeft(y, STR_COPROC_TEMP);
if (Coproc_read==0) { if (Coproc_read==0) {
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, "Co Proc NACK",INVERS); lcdDrawText(MENU_DEBUG_COL1_OFS, y, "Co Proc NACK",INVERS);
} }
else if (Coproc_read==0x81) { else if (Coproc_read==0x81) {
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, "Inst.TinyApp",INVERS); lcdDrawText(MENU_DEBUG_COL1_OFS, y, "Inst.TinyApp",INVERS);
} }
else if (Coproc_read<3) { else if (Coproc_read<3) {
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, "Upgr.TinyApp",INVERS); lcdDrawText(MENU_DEBUG_COL1_OFS, y, "Upgr.TinyApp",INVERS);
} }
else { else {
drawValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, Coproc_temp, UNIT_TEMPERATURE, LEFT); drawValueWithUnit(MENU_DEBUG_COL1_OFS, y, Coproc_temp, UNIT_TEMPERATURE, LEFT);
drawValueWithUnit(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_COPROC, Coproc_maxtemp, UNIT_TEMPERATURE, LEFT); drawValueWithUnit(MENU_DEBUG_COL2_OFS, y, Coproc_maxtemp, UNIT_TEMPERATURE, LEFT);
} }
y += FH;
#endif #endif
#if defined(PCBTARANIS) #if defined(STM32) && !defined(SIMU) && defined(DEBUG)
#if !defined(SIMU) && defined(DEBUG) lcdDrawTextAlignedLeft(y, "Usb");
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_USB, "Usb"); lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, charsWritten, LEFT);
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_USB, charsWritten, LEFT); lcdDrawText(lcdLastRightPos, y, " ");
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_USB, " "); lcdDrawNumber(lcdLastRightPos, y, APP_Rx_ptr_in, LEFT);
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_Y_USB, APP_Rx_ptr_in, LEFT); lcdDrawText(lcdLastRightPos, y, " ");
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_USB, " "); lcdDrawNumber(lcdLastRightPos, y, APP_Rx_ptr_out, LEFT);
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_Y_USB, APP_Rx_ptr_out, LEFT); lcdDrawText(lcdLastRightPos, y, " ");
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_USB, " "); lcdDrawNumber(lcdLastRightPos, y, usbWraps, LEFT);
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_Y_USB, usbWraps, LEFT); y += FH;
#endif #endif
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_FREE_RAM, "Free Mem");
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_FREE_RAM, availableMemory(), LEFT); #if defined(STM32)
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_FREE_RAM, "b"); lcdDrawTextAlignedLeft(y, "Free Mem");
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, availableMemory(), LEFT);
lcdDrawText(lcdLastRightPos, y, "b");
y += FH;
#endif
#if defined(LUA) #if defined(LUA)
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_LUA, "Lua scripts"); lcdDrawTextAlignedLeft(y, "Lua scripts");
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_LUA+1, "[D]", SMLSIZE); lcdDrawText(MENU_DEBUG_COL1_OFS, y+1, "[D]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_Y_LUA, 10*maxLuaDuration, LEFT); lcdDrawNumber(lcdLastRightPos, y, 10*maxLuaDuration, LEFT);
lcdDrawText(lcdLastRightPos+2, MENU_DEBUG_Y_LUA+1, "[I]", SMLSIZE); lcdDrawText(lcdLastRightPos+2, y+1, "[I]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_Y_LUA, 10*maxLuaInterval, LEFT); lcdDrawNumber(lcdLastRightPos, y, 10*maxLuaInterval, LEFT);
#endif // LUA y += FH;
#endif // PCBTARANIS #endif
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_MIXMAX, STR_TMIXMAXMS); lcdDrawTextAlignedLeft(y, STR_TMIXMAXMS);
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MIXMAX, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT); lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT);
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_MIXMAX, "ms"); lcdDrawText(lcdLastRightPos, y, "ms");
y += FH;
lcdDrawTextAlignedLeft(MENU_DEBUG_Y_RTOS, STR_FREESTACKMINB); lcdDrawTextAlignedLeft(y, STR_FREE_STACK);
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_RTOS, menusStack.available(), LEFT|SMLSIZE); lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, menusStack.available(), LEFT);
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_RTOS, "/"); lcdDrawText(lcdLastRightPos, y, "/");
lcdDrawNumber(lcdLastRightPos+1, MENU_DEBUG_Y_RTOS, mixerStack.available(), LEFT|SMLSIZE); lcdDrawNumber(lcdLastRightPos, y, mixerStack.available(), LEFT);
lcdDrawText(lcdLastRightPos, MENU_DEBUG_Y_RTOS, "/"); lcdDrawText(lcdLastRightPos, y, "/");
lcdDrawNumber(lcdLastRightPos+1, MENU_DEBUG_Y_RTOS, audioStack.available(), LEFT|SMLSIZE); lcdDrawNumber(lcdLastRightPos, y, audioStack.available(), LEFT);
y += FH;
#if defined(DEBUG_LATENCY)
lcdDrawTextAlignedLeft(y, "Hearbeat");
if (heartbeatCapture.valid)
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, heartbeatCapture.count, LEFT);
else
lcdDrawText(MENU_DEBUG_COL1_OFS, y, "---");
y += FH;
#endif
lcdDrawText(4*FW, 7*FH+1, STR_MENUTORESET); lcdDrawText(4*FW, 7*FH+1, STR_MENUTORESET);
lcdInvertLastLine(); lcdInvertLastLine();
@ -269,12 +279,16 @@ void menuStatisticsDebug2(event_t event)
break; break;
} }
lcdDrawTextAlignedLeft(MENU_DEBUG_ROW1, "Tlm RX Err"); uint8_t y = FH + 1;
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_ROW1, telemetryErrors, RIGHT);
#if defined(PCBX7) lcdDrawTextAlignedLeft(y, "Tlm RX Err");
lcdDrawTextAlignedLeft(MENU_DEBUG_ROW2, "BT status"); lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, telemetryErrors, RIGHT);
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_ROW2, IS_BLUETOOTH_CHIP_PRESENT(), RIGHT); y += FH;
#if defined(BLUETOOTH)
lcdDrawTextAlignedLeft(y, "BT status");
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, IS_BLUETOOTH_CHIP_PRESENT(), RIGHT);
y += FH;
#endif #endif
lcdDrawText(4*FW, 7*FH+1, STR_MENUTORESET); lcdDrawText(4*FW, 7*FH+1, STR_MENUTORESET);

View file

@ -184,7 +184,7 @@ void menuStatisticsDebug(event_t event)
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_ROW4, usbWraps, LEFT); lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_ROW4, usbWraps, LEFT);
#endif #endif
lcdDrawTextAlignedLeft(MENU_DEBUG_ROW5, STR_FREESTACKMINB); lcdDrawTextAlignedLeft(MENU_DEBUG_ROW5, STR_FREE_STACK);
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_ROW5+1, "[M]", SMLSIZE); lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_ROW5+1, "[M]", SMLSIZE);
lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_ROW5, menusStack.available(), LEFT); lcdDrawNumber(lcdLastRightPos, MENU_DEBUG_ROW5, menusStack.available(), LEFT);
lcdDrawText(lcdLastRightPos+2, MENU_DEBUG_ROW5+1, "[X]", SMLSIZE); lcdDrawText(lcdLastRightPos+2, MENU_DEBUG_ROW5+1, "[X]", SMLSIZE);

View file

@ -114,7 +114,7 @@ bool menuStatsDebug(event_t event)
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, STR_TMIXMAXMS); lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, STR_TMIXMAXMS);
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT, 0, NULL, "ms"); lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT, 0, NULL, "ms");
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, STR_FREESTACKMINB); lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, STR_FREE_STACK);
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH+1, "[Menus]", HEADER_COLOR|SMLSIZE); lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH+1, "[Menus]", HEADER_COLOR|SMLSIZE);
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, menusStack.available(), LEFT); lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, menusStack.available(), LEFT);
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+2*FH+1, "[Mix]", HEADER_COLOR|SMLSIZE); lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+2*FH+1, "[Mix]", HEADER_COLOR|SMLSIZE);

View file

@ -47,6 +47,10 @@ union ReusableBuffer reusableBuffer __DMA;
uint8_t* MSC_BOT_Data = reusableBuffer.MSC_BOT_Data; uint8_t* MSC_BOT_Data = reusableBuffer.MSC_BOT_Data;
#endif #endif
#if defined(DEBUG_LATENCY)
uint8_t latencyToggleSwitch = 0;
#endif
const uint8_t bchout_ar[] = { const uint8_t bchout_ar[] = {
0x1B, 0x1E, 0x27, 0x2D, 0x36, 0x39, 0x1B, 0x1E, 0x27, 0x2D, 0x36, 0x39,
0x4B, 0x4E, 0x63, 0x6C, 0x72, 0x78, 0x4B, 0x4E, 0x63, 0x6C, 0x72, 0x78,
@ -1339,6 +1343,19 @@ void doMixerCalculations()
static tmr10ms_t lastTMR = 0; static tmr10ms_t lastTMR = 0;
tmr10ms_t tmr10ms = get_tmr10ms(); tmr10ms_t tmr10ms = get_tmr10ms();
#if defined(DEBUG_LATENCY)
static tmr10ms_t lastLatencyToggle = 0;
if (tmr10ms - lastLatencyToggle >= 10) {
lastLatencyToggle = tmr10ms;
latencyToggleSwitch ^= 1;
if (latencyToggleSwitch)
sportUpdatePowerOn();
else
sportUpdatePowerOff();
}
#endif
uint8_t tick10ms = (tmr10ms >= lastTMR ? tmr10ms - lastTMR : 1); uint8_t tick10ms = (tmr10ms >= lastTMR ? tmr10ms - lastTMR : 1);
// handle tick10ms overrun // handle tick10ms overrun
// correct overflow handling costs a lot of code; happens only each 11 min; // correct overflow handling costs a lot of code; happens only each 11 min;

View file

@ -1386,4 +1386,8 @@ inline bool isSimu()
#endif #endif
} }
#if defined(DEBUG_LATENCY)
extern uint8_t latencyToggleSwitch;
#endif
#endif // _OPENTX_H_ #endif // _OPENTX_H_

View file

@ -272,7 +272,14 @@ void setupPulsesInternalModule(uint8_t protocol)
#if defined(PXX2) #if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2: case PROTOCOL_CHANNELS_PXX2:
intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE); intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE);
scheduleNextMixerCalculation(INTERNAL_MODULE, moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER ? PXX2_TOOLS_PERIOD : PXX2_PERIOD); if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) {
scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_TOOLS_PERIOD);
}
#if !defined(INTMDULE_HEARTBEAT)
else {
scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD);
}
#endif
break; break;
#endif #endif

View file

@ -58,8 +58,12 @@ template <class T, int SIZE>
class PulsesBuffer: public DataBuffer<T, SIZE> { class PulsesBuffer: public DataBuffer<T, SIZE> {
public: public:
T getLast() { T getLast() {
return *(DataBuffer<T, SIZE>::ptr - 1); return *(DataBuffer<T, SIZE>::ptr - 1);
}; };
void setLast(T value) {
*(DataBuffer<T, SIZE>::ptr - 1) = value;
}
}; };
#endif #endif

View file

@ -23,6 +23,14 @@
#include "pxx.h" #include "pxx.h"
struct HeartbeatCapture {
uint32_t timestamp;
uint32_t count;
uint8_t valid;
};
extern volatile HeartbeatCapture heartbeatCapture;
class Pxx1CrcMixin { class Pxx1CrcMixin {
protected: protected:
void initCrc() void initCrc()

View file

@ -60,6 +60,12 @@ void Pxx2Pulses::addChannels(uint8_t module)
for (int8_t i = 0; i < count; i++, channel++) { for (int8_t i = 0; i < count; i++, channel++) {
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
pulseValue = limit(1, (value * 512 / 682) + 1024, 2046); pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
#if defined(DEBUG_LATENCY_RF_ONLY)
if (latencyToggleSwitch)
pulseValue = 1;
else
pulseValue = 2046;
#endif
if (i & 1) if (i & 1)
addPulsesValues(pulseValueLow, pulseValue); addPulsesValues(pulseValueLow, pulseValue);
else else

View file

@ -321,6 +321,11 @@ char * getSwitchString(char * dest, swsrc_t idx)
else if (idx == SWSRC_TELEMETRY_STREAMING) { else if (idx == SWSRC_TELEMETRY_STREAMING) {
strcpy(s, "Tele"); strcpy(s, "Tele");
} }
#if defined(DEBUG_LATENCY)
else if (idx == SWSRC_LATENCY_TOGGLE) {
strcpy(s, "Ltc");
}
#endif
else { else {
zchar2str(s, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN); zchar2str(s, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN);
} }

View file

@ -431,6 +431,11 @@ bool getSwitch(swsrc_t swtch, uint8_t flags)
else if (cs_idx == SWSRC_ON) { else if (cs_idx == SWSRC_ON) {
result = true; result = true;
} }
#if defined(DEBUG_LATENCY)
else if (cs_idx == SWSRC_LATENCY_TOGGLE) {
result = latencyToggleSwitch;
}
#endif
else if (cs_idx <= SWSRC_LAST_SWITCH) { else if (cs_idx <= SWSRC_LAST_SWITCH) {
#if defined(PCBTARANIS) || defined(PCBHORUS) #if defined(PCBTARANIS) || defined(PCBHORUS)
if (flags & GETSWITCH_MIDPOS_DELAY) if (flags & GETSWITCH_MIDPOS_DELAY)

View file

@ -17,6 +17,7 @@ option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger
option(MULTI_SPORT "SPORT telemetry support" OFF) option(MULTI_SPORT "SPORT telemetry support" OFF)
option(SUPPORT_D16_EU_ONLY "XJT module only supports D16-EU and LR12-EU" OFF) # TODO rename to XJT_EU_ONLY option(SUPPORT_D16_EU_ONLY "XJT module only supports D16-EU and LR12-EU" OFF) # TODO rename to XJT_EU_ONLY
option(DEBUG_INTERRUPTS "Count interrupts" OFF) option(DEBUG_INTERRUPTS "Count interrupts" OFF)
option(DEBUG_LATENCY "Debug latency" OFF)
option(DEBUG_USB_INTERRUPTS "Count individual USB interrupts" OFF) option(DEBUG_USB_INTERRUPTS "Count individual USB interrupts" OFF)
option(DEBUG_TASKS "Task switching statistics" OFF) option(DEBUG_TASKS "Task switching statistics" OFF)
option(DEBUG_TIMERS "Time critical parts of the code" OFF) option(DEBUG_TIMERS "Time critical parts of the code" OFF)
@ -71,6 +72,17 @@ if(DEBUG_TIMERS)
set(DEBUG ON) set(DEBUG ON)
endif() endif()
if(DEBUG_LATENCY STREQUAL MIXER_RF)
add_definitions(-DDEBUG_LATENCY)
add_definitions(-DDEBUG_LATENCY_MIXER_RF)
endif()
if(DEBUG_LATENCY STREQUAL RF_ONLY)
add_definitions(-DDEBUG_LATENCY)
add_definitions(-DDEBUG_LATENCY_RF_ONLY)
endif()
if(CLI) if(CLI)
add_definitions(-DCLI) add_definitions(-DCLI)
set(FIRMWARE_SRC ${FIRMWARE_SRC} cli.cpp) set(FIRMWARE_SRC ${FIRMWARE_SRC} cli.cpp)

View file

@ -1,60 +0,0 @@
/*
* 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"
volatile uint32_t HearbeatCapture = 0;
void init_xjt_heartbeat()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = HEARTBEAT_GPIO_PIN;
GPIO_Init(HEARTBEAT_GPIO, &GPIO_InitStructure);
SYSCFG_EXTILineConfig(HEARTBEAT_EXTI_PortSource, HEARTBEAT_EXTI_PinSource);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = HEARTBEAT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_SetPriority(HEARTBEAT_EXTI_IRQn, 0); // Highest priority interrupt
NVIC_EnableIRQ(HEARTBEAT_EXTI_IRQn);
}
void stop_xjt_heartbeat()
{
NVIC_DisableIRQ(HEARTBEAT_EXTI_IRQn);
}
extern "C" void HEARTBEAT_EXTI_IRQHandler()
{
if (EXTI_GetITStatus(HEARTBEAT_EXTI_LINE) != RESET) {
HearbeatCapture = TIMER_2MHz_TIMER->CNT;
EXTI_ClearITPendingBit(HEARTBEAT_EXTI_LINE);
}
}

View file

@ -0,0 +1,83 @@
/*
* 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"
volatile HeartbeatCapture heartbeatCapture;
#if defined(INTMODULE_HEARTBEAT_GPIO)
void init_intmodule_heartbeat()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = INTMODULE_HEARTBEAT_GPIO_PIN;
GPIO_Init(INTMODULE_HEARTBEAT_GPIO, &GPIO_InitStructure);
SYSCFG_EXTILineConfig(INTMODULE_HEARTBEAT_EXTI_PortSource, INTMODULE_HEARTBEAT_EXTI_PinSource);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = INTMODULE_HEARTBEAT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_SetPriority(INTMODULE_HEARTBEAT_EXTI_IRQn, 0); // Highest priority interrupt
NVIC_EnableIRQ(INTMODULE_HEARTBEAT_EXTI_IRQn);
heartbeatCapture.valid = true;
}
void stop_intmodule_heartbeat()
{
heartbeatCapture.valid = false;
#if !defined(INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER)
NVIC_DisableIRQ(INTMODULE_HEARTBEAT_EXTI_IRQn);
#endif
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = INTMODULE_HEARTBEAT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = INTMODULE_HEARTBEAT_TRIGGER;
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
EXTI_Init(&EXTI_InitStructure);
}
void check_xjt_heartbeat()
{
if (EXTI_GetITStatus(INTMODULE_HEARTBEAT_EXTI_LINE) != RESET) {
heartbeatCapture.timestamp = TIMER_2MHz_TIMER->CNT;
heartbeatCapture.count++;
EXTI_ClearITPendingBit(INTMODULE_HEARTBEAT_EXTI_LINE);
}
}
#endif
#if defined(INTMDULE_HEARTBEAT) && !defined(INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER)
extern "C" void INTMODULE_HEARTBEAT_EXTI_IRQHandler()
{
check_xjt_heartbeat();
}
#endif

View file

@ -90,6 +90,10 @@ extern "C" void ROTARY_ENCODER_EXTI_IRQHandler1(void)
EXTI_ClearITPendingBit(ROTARY_ENCODER_EXTI_LINE2); EXTI_ClearITPendingBit(ROTARY_ENCODER_EXTI_LINE2);
} }
#endif #endif
#if !defined(BOOT) && defined(INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER)
check_xjt_heartbeat();
#endif
} }
#if defined(ROTARY_ENCODER_EXTI_IRQn2) #if defined(ROTARY_ENCODER_EXTI_IRQn2)

View file

@ -626,8 +626,9 @@
// Heartbeat (not used) // Heartbeat (not used)
#define TRAINER_MODULE_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define TRAINER_MODULE_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define HEARTBEAT_GPIO GPIOD #define INTMODULE_HEARTBEAT_GPIO GPIOD
#define HEARTBEAT_GPIO_PIN GPIO_Pin_12 // PD.12 #define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_12 // PD.12
#define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Falling
// Trainer Port // Trainer Port
#define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA1) #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA1)

View file

@ -255,6 +255,7 @@ set(TARGET_SRC
trainer_driver.cpp trainer_driver.cpp
../common/arm/stm32/audio_dac_driver.cpp ../common/arm/stm32/audio_dac_driver.cpp
../common/arm/stm32/adc_driver.cpp ../common/arm/stm32/adc_driver.cpp
../common/arm/stm32/heartbeat_driver.cpp
) )
if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES) if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES)

View file

@ -362,14 +362,15 @@ void checkTrainerSettings()
stop_trainer_ppm(); stop_trainer_ppm();
break; break;
case TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE: case TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE:
stop_trainer_module_cppm() ; stop_trainer_module_cppm();
break; break;
case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE: case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE:
stop_trainer_module_sbus() ; stop_trainer_module_sbus();
break; break;
#if defined(TRAINER_BATTERY_COMPARTMENT) #if defined(TRAINER_BATTERY_COMPARTMENT)
case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT:
auxSerialStop(); auxSerialStop();
break;
#endif #endif
} }
@ -397,6 +398,11 @@ void checkTrainerSettings()
init_trainer_capture(); init_trainer_capture();
break; break;
} }
if (requiredTrainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE || requiredTrainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE)
stop_intmodule_heartbeat();
else
init_intmodule_heartbeat();
} }
} }

View file

@ -270,6 +270,16 @@ void extmoduleSendNextFrame();
#define stop_trainer_module_sbus() #define stop_trainer_module_sbus()
#endif #endif
#if defined(INTMODULE_HEARTBEAT_GPIO)
void init_intmodule_heartbeat();
void stop_intmodule_heartbeat();
void check_xjt_heartbeat();
#else
#define init_intmodule_heartbeat()
#define stop_intmodule_heartbeat()
#define check_xjt_heartbeat()
#endif
// SBUS // SBUS
int sbusGetByte(uint8_t * byte); int sbusGetByte(uint8_t * byte);

View file

@ -1164,36 +1164,80 @@
#define SPORT_UPDATE_RCC_AHB1Periph 0 #define SPORT_UPDATE_RCC_AHB1Periph 0
#endif #endif
// Heartbeat for XJT synchro #if defined(PCBXLITES) || defined(PCBX9LITE)
#if defined(PCBXLITE) || defined(PCBX9LITE) #define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Rising
#define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define HEARTBEAT_GPIO GPIOD
#define HEARTBEAT_GPIO_PIN GPIO_Pin_15
#define HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOD
#define HEARTBEAT_EXTI_PinSource GPIO_PinSource15
#define HEARTBEAT_EXTI_LINE EXTI_Line15
#define HEARTBEAT_EXTI_IRQn EXTI15_10_IRQn
#define HEARTBEAT_EXTI_IRQHandler EXTI15_10_IRQHandler
#else #else
#define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC #define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Falling
#define HEARTBEAT_GPIO GPIOC #endif
#define HEARTBEAT_GPIO_PIN GPIO_Pin_7
#define HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOC // Heartbeat for iXJT / ISRM synchro
#define HEARTBEAT_EXTI_PinSource GPIO_PinSource7 #if defined(PCBXLITE)
#define HEARTBEAT_EXTI_LINE EXTI_Line7 #define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn #define INTMODULE_HEARTBEAT_GPIO GPIOD
#define HEARTBEAT_EXTI_IRQHandler EXTI9_5_IRQHandler #define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_15
#define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOD
#define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource15
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line15
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI15_10_IRQn
#define INTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI15_10_IRQHandler
#elif defined(PCBX9LITE)
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
// #define INTMODULE_HEARTBEAT_GPIO GPIOC
// #define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_9
#define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOC
#define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource9
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line9
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn
#define INTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI9_5_IRQHandler
#elif defined(RADIO_X7)
#define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
#define INTMODULE_HEARTBEAT_GPIO GPIOC
#define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_7
#define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOC
#define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource7
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line7
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn
#else
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
#define INTMODULE_HEARTBEAT_GPIO GPIOC
#define INTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_7
#define INTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOC
#define INTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource7
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line7
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI9_5_IRQn
#define INTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI9_5_IRQHandler
#endif
#if defined(PCBX9LITE)
#define EXTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define EXTMODULE_HEARTBEAT_GPIO GPIOD
#define EXTMODULE_HEARTBEAT_GPIO_PIN GPIO_Pin_15
#define EXTMODULE_HEARTBEAT_EXTI_PortSource EXTI_PortSourceGPIOD
#define EXTMODULE_HEARTBEAT_EXTI_PinSource GPIO_PinSource15
#define EXTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line15
#define EXTMODULE_HEARTBEAT_EXTI_IRQn EXTI15_10_IRQn
#define EXTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI15_10_IRQHandler
#endif #endif
// Trainer / Trainee from the module bay // Trainer / Trainee from the module bay
#if defined(PCBXLITE) || defined(PCBX9LITE) #if defined(PCBX9LITE)
#define TRAINER_MODULE_CPPM #define TRAINER_MODULE_CPPM
#define TRAINER_MODULE_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define TRAINER_MODULE_RCC_AHB1Periph EXTMODULE_HEARTBEAT_RCC_AHB1Periph
#define TRAINER_MODULE_RCC_APB1Periph RCC_APB1Periph_TIM4 #define TRAINER_MODULE_RCC_APB1Periph RCC_APB1Periph_TIM4
#define TRAINER_MODULE_RCC_APB2Periph 0 #define TRAINER_MODULE_RCC_APB2Periph 0
#define TRAINER_MODULE_CPPM_GPIO HEARTBEAT_GPIO #define TRAINER_MODULE_CPPM_GPIO EXTMODULE_HEARTBEAT_GPIO
#define TRAINER_MODULE_CPPM_GPIO_PIN HEARTBEAT_GPIO_PIN #define TRAINER_MODULE_CPPM_GPIO_PIN EXTMODULE_HEARTBEAT_GPIO_PIN
#define TRAINER_MODULE_CPPM_GPIO_PinSource GPIO_PinSource15 #define TRAINER_MODULE_CPPM_GPIO_PinSource EXTMODULE_HEARTBEAT_EXTI_PinSource
#define TRAINER_MODULE_CPPM_GPIO_AF GPIO_AF_TIM4
#elif defined(PCBXLITE)
#define TRAINER_MODULE_CPPM
#define TRAINER_MODULE_RCC_AHB1Periph INTMODULE_HEARTBEAT_RCC_AHB1Periph
#define TRAINER_MODULE_RCC_APB1Periph RCC_APB1Periph_TIM4
#define TRAINER_MODULE_RCC_APB2Periph 0
#define TRAINER_MODULE_CPPM_GPIO INTMODULE_HEARTBEAT_GPIO
#define TRAINER_MODULE_CPPM_GPIO_PIN INTMODULE_HEARTBEAT_GPIO_PIN
#define TRAINER_MODULE_CPPM_GPIO_PinSource INTMODULE_HEARTBEAT_EXTI_PinSource
#define TRAINER_MODULE_CPPM_GPIO_AF GPIO_AF_TIM4 #define TRAINER_MODULE_CPPM_GPIO_AF GPIO_AF_TIM4
#else #else
#define TRAINER_MODULE_CPPM #define TRAINER_MODULE_CPPM
@ -1201,9 +1245,9 @@
#define TRAINER_MODULE_RCC_AHB1Periph RCC_AHB1Periph_GPIOC #define TRAINER_MODULE_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
#define TRAINER_MODULE_RCC_APB2Periph RCC_APB2Periph_USART6 #define TRAINER_MODULE_RCC_APB2Periph RCC_APB2Periph_USART6
#define TRAINER_MODULE_RCC_APB1Periph RCC_APB1Periph_TIM3 #define TRAINER_MODULE_RCC_APB1Periph RCC_APB1Periph_TIM3
#define TRAINER_MODULE_CPPM_GPIO HEARTBEAT_GPIO #define TRAINER_MODULE_CPPM_GPIO INTMODULE_HEARTBEAT_GPIO
#define TRAINER_MODULE_CPPM_GPIO_PIN HEARTBEAT_GPIO_PIN #define TRAINER_MODULE_CPPM_GPIO_PIN INTMODULE_HEARTBEAT_GPIO_PIN
#define TRAINER_MODULE_CPPM_GPIO_PinSource GPIO_PinSource7 #define TRAINER_MODULE_CPPM_GPIO_PinSource INTMODULE_HEARTBEAT_EXTI_PinSource
#define TRAINER_MODULE_SBUS_GPIO_AF GPIO_AF_USART6 #define TRAINER_MODULE_SBUS_GPIO_AF GPIO_AF_USART6
#define TRAINER_MODULE_CPPM_GPIO_AF GPIO_AF_TIM3 #define TRAINER_MODULE_CPPM_GPIO_AF GPIO_AF_TIM3
#define TRAINER_MODULE_SBUS_USART USART6 #define TRAINER_MODULE_SBUS_USART USART6

View file

@ -20,8 +20,6 @@
#include "opentx.h" #include "opentx.h"
extern volatile uint32_t HeartbeatCapture;
void intmoduleStop() void intmoduleStop()
{ {
INTERNAL_MODULE_OFF(); INTERNAL_MODULE_OFF();
@ -34,17 +32,27 @@ void intmoduleStop()
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
} }
#if defined(DEBUG_LATENCY)
#define HEARBEAT_OFFSET unsigned(5500 + g_model.flightModeData[0].gvars[0] * 100)
#else
constexpr int HEARBEAT_OFFSET = 5500;
#endif
void intmoduleSendNextFrame() void intmoduleSendNextFrame()
{ {
switch (moduleState[INTERNAL_MODULE].protocol) { switch (moduleState[INTERNAL_MODULE].protocol) {
#if defined(PXX1) #if defined(PXX1)
case PROTOCOL_CHANNELS_PXX1_PULSES: case PROTOCOL_CHANNELS_PXX1_PULSES:
{ {
#if 0 uint32_t last = intmodulePulsesData.pxx.getLast();
// TODO this will be needed if we want to use HEARTBEAT for synchro with the module if (heartbeatCapture.valid) {
INTMODULE_TIMER->ARR = TIMER_2MHz_TIMER->CNT - HeartbeatCapture > 0x2A00 ? 17979 : 18019; if (TIMER_2MHz_TIMER->CNT - heartbeatCapture.timestamp > HEARBEAT_OFFSET)
#endif last -= 21;
INTMODULE_TIMER->CCR2 = intmodulePulsesData.pxx.getLast() - 4000; // 2mS in advance else
last += 19;
intmodulePulsesData.pxx.setLast(last);
}
INTMODULE_TIMER->CCR2 = last - 4000; // 2mS in advance
INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA 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->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->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);

View file

@ -134,17 +134,28 @@ TASK_FUNCTION(mixerTask)
uint32_t now = RTOS_GET_MS(); uint32_t now = RTOS_GET_MS();
bool run = false; bool run = false;
if ((now - lastRunTime) >= 10) { // run at least every 10ms
if ((now - lastRunTime) >= 10) {
// run at least every 10ms
run = true; run = true;
} }
else if (now == nextMixerTime[0]) {
run = true; #if defined(PXX2) && defined(INTMDULE_HEARTBEAT)
} if (moduleState[0].protocol == PROTOCOL_CHANNELS_PXX2 && heartbeatCapture.valid && heartbeatCapture.timestamp > lastRunTime) {
#if NUM_MODULES >= 2
else if (now == nextMixerTime[1]) {
run = true; run = true;
} }
#endif #endif
if (now == nextMixerTime[0]) {
run = true;
}
#if NUM_MODULES >= 2
if (now == nextMixerTime[1]) {
run = true;
}
#endif
if (!run) { if (!run) {
continue; // go back to sleep continue; // go back to sleep
} }

View file

@ -210,7 +210,7 @@ const char STR_TX[] = TR_TXnRX;
const char STR_NODATA[] = TR_NODATA; const char STR_NODATA[] = TR_NODATA;
const char STR_US[] = TR_US; const char STR_US[] = TR_US;
const char STR_TMIXMAXMS[] = TR_TMIXMAXMS; const char STR_TMIXMAXMS[] = TR_TMIXMAXMS;
const char STR_FREESTACKMINB[] = TR_FREESTACKMINB; const char STR_FREE_STACK[] = TR_FREE_STACK;
const char STR_MENUTORESET[] = TR_MENUTORESET; const char STR_MENUTORESET[] = TR_MENUTORESET;
const char STR_PPM_TRAINER[] = TR_PPM_TRAINER; const char STR_PPM_TRAINER[] = TR_PPM_TRAINER;
const char STR_CH[] = TR_CH; const char STR_CH[] = TR_CH;

View file

@ -333,7 +333,7 @@ extern const char STR_TX[];
extern const char STR_NODATA[]; extern const char STR_NODATA[];
extern const char STR_US[]; extern const char STR_US[];
extern const char STR_TMIXMAXMS[]; extern const char STR_TMIXMAXMS[];
extern const char STR_FREESTACKMINB[]; extern const char STR_FREE_STACK[];
extern const char STR_MENUTORESET[]; extern const char STR_MENUTORESET[];
extern const char STR_PPM_TRAINER[]; extern const char STR_PPM_TRAINER[];
extern const char STR_CH[]; extern const char STR_CH[];

View file

@ -639,7 +639,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER" >> Reset" #define TR_MENUTORESET CENTER TR_ENTER" >> Reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -648,7 +648,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Freier Stack" #define TR_FREE_STACK "Freier Stack"
#define TR_MENUTORESET CENTER TR_ENTER " für Reset" #define TR_MENUTORESET CENTER TR_ENTER " für Reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -643,7 +643,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER " to reset" #define TR_MENUTORESET CENTER TR_ENTER " to reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -653,7 +653,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER "Resetear" #define TR_MENUTORESET CENTER TR_ENTER "Resetear"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -646,7 +646,7 @@
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER " to reset" #define TR_MENUTORESET CENTER TR_ENTER " to reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"

View file

@ -657,7 +657,7 @@
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER" pour reset" #define TR_MENUTORESET CENTER TR_ENTER" pour reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"

View file

@ -656,7 +656,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER" x Azzerare" #define TR_MENUTORESET CENTER TR_ENTER" x Azzerare"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -642,7 +642,7 @@ TR_GYR_VSRCRAW
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER" voor Reset" #define TR_MENUTORESET CENTER TR_ENTER" voor Reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -656,7 +656,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "TmixMaks" #define TR_TMIXMAXMS "TmixMaks"
#define TR_FREESTACKMINB "Wolny stos" #define TR_FREE_STACK "Wolny stos"
#define TR_MENUTORESET CENTER TR_ENTER " >> Reset" #define TR_MENUTORESET CENTER TR_ENTER " >> Reset"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "KN" #define TR_CH "KN"

View file

@ -638,7 +638,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER" Reinicia" #define TR_MENUTORESET CENTER TR_ENTER" Reinicia"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "CH" #define TR_CH "CH"

View file

@ -655,7 +655,7 @@
#define TR_US "us" #define TR_US "us"
#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us"
#define TR_TMIXMAXMS "Tmix max" #define TR_TMIXMAXMS "Tmix max"
#define TR_FREESTACKMINB "Free Stack" #define TR_FREE_STACK "Free stack"
#define TR_MENUTORESET CENTER TR_ENTER " Nollar" #define TR_MENUTORESET CENTER TR_ENTER " Nollar"
#define TR_PPM_TRAINER "TR" #define TR_PPM_TRAINER "TR"
#define TR_CH "KN" #define TR_CH "KN"