Merge with latest 2.3

This commit is contained in:
Bertrand Songis
2021-04-06 09:40:48 +02:00
141 changed files with 5093 additions and 3760 deletions
+1
View File
@@ -382,6 +382,7 @@ set(SRC
strhelpers.cpp
switches.cpp
mixer.cpp
mixer_scheduler.cpp
stamp.cpp
timers.cpp
trainer.cpp
+1 -1
View File
@@ -161,7 +161,7 @@ const char * const unitsFilenames[] = {
"hertz",
"ms",
"us",
"spare4",
"km",
"spare5",
"spare6",
"spare7",
+5 -5
View File
@@ -699,11 +699,11 @@ int cliTrace(const char ** argv)
int cliStackInfo(const char ** argv)
{
serialPrint("[MAIN] %d available / %d", stackAvailable(), stackSize());
serialPrint("[MENUS] %d available / %d", menusStack.available(), menusStack.size());
serialPrint("[MIXER] %d available / %d", mixerStack.available(), mixerStack.size());
serialPrint("[AUDIO] %d available / %d", audioStack.available(), audioStack.size());
serialPrint("[CLI] %d available / %d", cliStack.available(), cliStack.size());
serialPrint("[MAIN] %d available / %d bytes", stackAvailable()*4, stackSize()*4);
serialPrint("[MENUS] %d available / %d bytes", menusStack.available()*4, menusStack.size());
serialPrint("[MIXER] %d available / %d bytes", mixerStack.available()*4, mixerStack.size());
serialPrint("[AUDIO] %d available / %d bytes", audioStack.available()*4, audioStack.size());
serialPrint("[CLI] %d available / %d bytes", cliStack.available()*4, cliStack.size());
return 0;
}
+3 -2
View File
@@ -278,6 +278,7 @@ enum TelemetryProtocol
PROTOCOL_TELEMETRY_FLYSKY_IBUS,
PROTOCOL_TELEMETRY_HITEC,
PROTOCOL_TELEMETRY_HOTT,
PROTOCOL_TELEMETRY_MLINK,
PROTOCOL_TELEMETRY_MULTIMODULE,
PROTOCOL_TELEMETRY_AFHDS3,
PROTOCOL_TELEMETRY_GHOST,
@@ -318,8 +319,8 @@ enum TelemetryUnit {
UNIT_HERTZ,
UNIT_MS,
UNIT_US,
UNIT_MAX = UNIT_US,
UNIT_SPARE4,
UNIT_KM,
UNIT_MAX = UNIT_KM,
UNIT_SPARE5,
UNIT_SPARE6,
UNIT_SPARE7,
+40 -78
View File
@@ -130,9 +130,6 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM,
#if defined(PCBSKY9X) && defined(REVX)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_OUTPUT_TYPE,
#endif
#if defined(AFHDS3)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER,
@@ -152,6 +149,9 @@ enum MenuModelSetupItems {
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_2,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_3,
#if defined(PCBSKY9X) && defined(REVX)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_OUTPUT_TYPE,
#endif
#if defined(PCBSKY9X)
ITEM_MODEL_SETUP_EXTRA_MODULE_LABEL,
ITEM_MODEL_SETUP_EXTRA_MODULE_CHANNELS,
@@ -212,8 +212,8 @@ enum MenuModelSetupItems {
#endif
#if defined(PCBSKY9X) && defined(REVX)
#define OUTPUT_TYPE_ROW (isModulePPM(EXTERNAL_MODULE) ? (uint8_t)0 : HIDDEN_ROW),
#elif defined(PCBSKY9X)
#define OUTPUT_TYPE_ROW (isModulePPM(EXTERNAL_MODULE) ? (uint8_t)0 : HIDDEN_ROW), // Output type (OpenDrain / PushPull)
#else
#define OUTPUT_TYPE_ROW
#endif
@@ -389,12 +389,22 @@ void editTimerCountdown(int timerIdx, coord_t y, LcdFlags attr, event_t event)
#define EXTERNAL_MODULE_ROWS
#endif
#if defined(PCBTARANIS)
#define WARN_ROWS \
SW_WARN_ROWS, /* Switch warning */ \
POT_WARN_ROWS, /* Pot warning */
#else
#define WARN_ROWS \
NUM_SWITCHES - 1, /* Switch warning */
#endif
void menuModelSetup(event_t event)
{
int8_t old_editMode = s_editMode;
#if defined(PCBTARANIS)
int8_t old_posHorz = menuHorizontalPosition;
#endif
MENU_TAB({
HEADER_LINE_COLUMNS
@@ -412,8 +422,7 @@ void menuModelSetup(event_t event)
LABEL(PreflightCheck),
0, // Checklist
0, // Throttle warning
SW_WARN_ROWS, // Switch warning
POT_WARN_ROWS, // Pot warning
WARN_ROWS
NUM_STICKS + NUM_POTS + NUM_SLIDERS - 1, // Center beeps
0, // Global functions
@@ -424,54 +433,12 @@ void menuModelSetup(event_t event)
EXTERNAL_MODULE_ROWS
TRAINER_ROWS
});
#else
MENU_TAB({
HEADER_LINE_COLUMNS
0,
TIMERS_ROWS,
0, // Extended limits
1, // Extended trims
0, // Show trims
0, // Trims step
0, // Throttle reverse
0, // Throttle trace source
0, // Throttle trim
0, // Throttle trim switch
LABEL(PreflightCheck),
0, // Checklist
0, // Throttle warning
NUM_SWITCHES-1, // Switch warning
NUM_STICKS+NUM_POTS+NUM_SLIDERS-1, // Center beeps
0, // Global functions
LABEL(ExternalModule),
MODULE_TYPE_ROWS(EXTERNAL_MODULE),
MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE)
MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE)
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE)
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum
0, // Output type (OpenDrain / PushPull)
MODULE_POWER_ROW(EXTERNAL_MODULE),
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)),
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE)
FAILSAFE_ROWS(EXTERNAL_MODULE),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 1
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 2
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 3
OUTPUT_TYPE_ROW
EXTRA_MODULE_ROWS
TRAINER_ROWS
});
#endif
MENU_CHECK(menuTabModel, MENU_MODEL_SETUP, HEADER_LINE + ITEM_MODEL_SETUP_LINES_COUNT);
title(STR_MENUSETUP);
@@ -1582,40 +1549,35 @@ void menuModelSetup(event_t event)
{
#if defined(MULTIMODULE)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
const char * title = getMultiOptionTitle(moduleIdx);
lcdDrawText(INDENT_WIDTH, y, title);
if (title == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
if (status.isValid()) {
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
if (attr && status.optionDisp == 2) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr) {
lcdDrawText(INDENT_WIDTH, y, pdef->optionsstr);
if (attr && pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
}
int8_t min, max;
getMultiOptionValues(multi_proto, min, max);
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
if (title == STR_MULTI_RFPOWER) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
min = 0;
max = 15;
}
else if (title == STR_MULTI_TELEMETRY) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_TELEMETRY_MODE, optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
else if (title == STR_MULTI_WBUS) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_WBUS_MODE, optionValue, LEFT | attr);
min = 0;
max = 1;
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
optionValue = optionValue & 0x01;
+22 -26
View File
@@ -1304,38 +1304,34 @@ void menuModelSetup(event_t event)
#if defined(MULTIMODULE)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
const char * title = getMultiOptionTitle(moduleIdx);
lcdDrawText(INDENT_WIDTH, y, title);
if (title == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol();
if (status.isValid()) {
lcdDrawText(INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
if (attr && status.optionDisp == 2) {
lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr)
lcdDrawText(INDENT_WIDTH, y, pdef->optionsstr);
if (pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT);
lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT);
lcdDrawText(lcdLastRightPos, y, ")", LEFT);
}
}
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
int8_t min, max;
getMultiOptionValues(multi_proto, min, max);
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
if (title == STR_MULTI_RFPOWER) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
}
else if (title == STR_MULTI_TELEMETRY) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_TELEMETRY_MODE, optionValue, LEFT | attr);
}
else if (title == STR_MULTI_WBUS) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_WBUS_MODE, optionValue, LEFT | attr);
min = 0;
max = 1;
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
optionValue = optionValue & 0x01;
editCheckBox(optionValue, MODEL_SETUP_2ND_COLUMN, y, "", LEFT | attr, event);
+22 -22
View File
@@ -1688,34 +1688,33 @@ bool menuModelSetup(event_t event)
{
#if defined(MULTIMODULE)
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
const char * title = getMultiOptionTitle(moduleIdx);
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, title);
if (title == STR_MULTI_RFTUNE) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
int optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
if (status.isValid()) {
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, mm_options_strings::options[status.optionDisp]);
if (attr && status.optionDisp == 2) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
}
else {
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
if (pdef->optionsstr) {
lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, pdef->optionsstr);
if (attr && pdef->optionsstr == STR_MULTI_RFTUNE) {
lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")");
}
}
}
int8_t min, max;
getMultiOptionValues(multi_proto, min, max);
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FRSKY_R9) {
if (title == STR_MULTI_RFPOWER) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_POWER, optionValue, LEFT | attr);
min = 0;
max = 15;
}
else if (title == STR_MULTI_TELEMETRY) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_TELEMETRY_MODE, optionValue, LEFT | attr);
}
else if (title == STR_MULTI_WBUS) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_WBUS_MODE, optionValue, LEFT | attr);
min = 0;
max = 1;
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, 50 + 5 * optionValue, LEFT | attr);
}
else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
optionValue = optionValue & 0x01;
@@ -1727,6 +1726,7 @@ bool menuModelSetup(event_t event)
else
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, optionValue, LEFT | attr);
}
if (attr) {
CHECK_INCDEC_MODELVAR(event, optionValue, min, max);
if (checkIncDec_Ret) {
@@ -145,7 +145,7 @@ void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, ui
if (c <= 0) v = -v;
}
else {
v = checkIncDec(event, abs(v), '0', 'z', 0);
v = checkIncDec(event, abs(v), ' ', 'z', 0);
}
}
+26 -1
View File
@@ -994,9 +994,15 @@ const char* mm_options_strings::options[] = {
STR_MULTI_SERVOFREQ,
STR_MULTI_MAX_THROW,
STR_MULTI_RFCHAN,
STR_MULTI_RFPOWER
STR_MULTI_RFPOWER,
STR_MULTI_WBUS
};
const uint8_t getMaxMultiOptions()
{
return DIM(mm_options_strings::options);
}
const mm_protocol_definition multi_protocols[] = {
// Protocol as defined in pulses\modules_constants.h, number of sub_protocols - 1, Failsafe supported, Disable channel mapping supported, Subtype string, Option type
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, true, STR_SUBTYPE_FLYSKY, nullptr},
@@ -1091,3 +1097,22 @@ void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, Lcd
else
lcdDrawMMM(x, y, flags);
}
#if defined(MULTIMODULE)
const char * getMultiOptionTitle(uint8_t moduleIdx)
{
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
if (status.isValid()) {
if (status.optionDisp >= getMaxMultiOptions()) {
status.optionDisp = 1; // Unknown options are defaulted to type 1 (basic option)
}
return mm_options_strings::options[status.optionDisp];
}
else {
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
return pdef->optionsstr;
}
}
#endif
+2 -1
View File
@@ -306,7 +306,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,
@@ -346,6 +346,7 @@ inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) {
}
void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags);
const char * getMultiOptionTitle(uint8_t moduleIdx);
const char * writeScreenshot();
+1
View File
@@ -24,6 +24,7 @@ if(PYTHONINTERP_FOUND)
add_lua_export_target(xlite ${LUA_INCLUDES} -DPCBTARANIS -DPCBXLITE)
add_lua_export_target(xlites ${LUA_INCLUDES} -DPCBTARANIS -DPCBXLITES -DPCBXLITE -DGYRO)
add_lua_export_target(x9d ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9D -DPCBX9)
add_lua_export_target(x9d+2019 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9D -DPCBX9 -DRADIO_X9DP2019)
add_lua_export_target(x9e ${LUA_INCLUDES} -DPCBTARANIS -DPCBX9E -DPCBX9)
add_lua_export_target(x10 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10)
add_lua_export_target(x12s ${LUA_INCLUDES} -DPCBHORUS -DPCBX12S)
+7 -1
View File
@@ -54,6 +54,8 @@
#include "lua/lua_exports_xlites.inc"
#elif defined(PCBXLITE)
#include "lua/lua_exports_xlite.inc"
#elif defined(RADIO_X9DP2019)
#include "lua/lua_exports_x9d+2019.inc"
#elif defined(PCBTARANIS)
#include "lua/lua_exports_x9d.inc"
#endif
@@ -1409,7 +1411,10 @@ Get RSSI value as well as low and critical RSSI alarm levels (in dB)
*/
static int luaGetRSSI(lua_State * L)
{
lua_pushunsigned(L, min((uint8_t)99, TELEMETRY_RSSI()));
if (TELEMETRY_STREAMING())
lua_pushunsigned(L, min((uint8_t)99, TELEMETRY_RSSI()));
else
lua_pushunsigned(L, 0);
lua_pushunsigned(L, g_model.rssiAlarms.getWarningRssi());
lua_pushunsigned(L, g_model.rssiAlarms.getCriticalRssi());
return 3;
@@ -2036,6 +2041,7 @@ const luaR_value_entry opentxConstants[] = {
{"UNIT_KMH", UNIT_KMH },
{"UNIT_MPH", UNIT_MPH },
{"UNIT_METERS", UNIT_METERS },
{"UNIT_KM", UNIT_KM },
{"UNIT_FEET", UNIT_FEET },
{"UNIT_CELSIUS", UNIT_CELSIUS },
{"UNIT_FAHRENHEIT", UNIT_FAHRENHEIT },
+82
View File
@@ -0,0 +1,82 @@
/*
* 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 defined(HARDWARE_INTERNAL_MODULE)
if (mixerSchedules[INTERNAL_MODULE].period) {
return mixerSchedules[INTERNAL_MODULE].period;
}
#endif
#if defined(HARDWARE_EXTERNAL_MODULE)
if (mixerSchedules[EXTERNAL_MODULE].period) {
return mixerSchedules[EXTERNAL_MODULE].period;
}
#endif
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
+84
View File
@@ -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 1750 /* 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
+13
View File
@@ -1445,6 +1445,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) {
+3 -2
View File
@@ -320,7 +320,7 @@ void memswap(void * a, void * b, uint8_t size);
#define MASK_CFN_TYPE uint64_t // current max = 64 function switches
#define MASK_FUNC_TYPE uint32_t // current max = 32 functions
typedef struct {
struct CustomFunctionsContext {
MASK_FUNC_TYPE activeFunctions;
MASK_CFN_TYPE activeSwitches;
tmr10ms_t lastFunctionTime[MAX_SPECIAL_FUNCTIONS];
@@ -334,7 +334,7 @@ typedef struct {
{
memclear(this, sizeof(*this));
}
} CustomFunctionsContext;
};
#include "strhelpers.h"
#include "gui.h"
@@ -501,6 +501,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 scheduleNextMixerCalculation(uint8_t module, uint32_t period_ms);
void checkTrims();
+1 -12
View File
@@ -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()
+2 -4
View File
@@ -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;
+2 -4
View File
@@ -42,6 +42,8 @@ struct mm_options_strings {
static const char* options[];
};
const uint8_t getMaxMultiOptions();
struct mm_protocol_definition {
uint8_t protocol;
uint8_t maxSubtype;
@@ -671,10 +673,6 @@ inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max)
min = -1;
max = 84;
break;
case MODULE_SUBTYPE_MULTI_FRSKY_R9:
min = 0; // 10mW
max = 5; // 300mW
break;
default:
min = -128;
max = 127;
-2
View File
@@ -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);
+129 -18
View File
@@ -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,81 @@ 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
#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:
#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
#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 +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
@@ -316,63 +345,102 @@ 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);
#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);
#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:
case PROTOCOL_CHANNELS_DSM2_DSM2:
case PROTOCOL_CHANNELS_DSM2_DSMX:
setupPulsesDSM2();
#if defined(PCBSKY9X)
scheduleNextMixerCalculation(EXTERNAL_MODULE, DSM2_PERIOD);
#endif
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();
#if defined(PCBSKY9X)
scheduleNextMixerCalculation(EXTERNAL_MODULE, CROSSFIRE_PERIOD);
#endif
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();
#if defined(PCBSKPCBSKY9X)
scheduleNextMixerCalculation(EXTERNAL_MODULE, GHOST_PERIOD);
#endif
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();
#if defined(PCBSKY9X)
scheduleNextMixerCalculation(EXTERNAL_MODULE, MULTIMODULE_PERIOD);
#endif
return true;
}
#endif
#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
default:
scheduleNextMixerCalculation(EXTERNAL_MODULE, 50/*ms*/);
return false;
}
}
@@ -386,12 +454,26 @@ 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)
init_intmodule_heartbeat();
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)
init_intmodule_heartbeat();
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD + 1000/*us*/);
#else
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
#endif
break;
#endif
@@ -399,6 +481,14 @@ 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)
init_intmodule_heartbeat();
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD + 1000/*us*/);
#else
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
#endif
break;
#endif
@@ -406,17 +496,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 +520,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,13 +540,14 @@ 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 + 2 /* backup */);
mixerSchedulerResetTimer();
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD + 2000 /* backup */);
#else
scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD);
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
#endif
}
return result;
@@ -463,23 +557,32 @@ 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;
}
}
void stopPulsesInternalModule()
{
if (moduleState[INTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
intmoduleStop();
moduleState[INTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
}
}
bool setupPulsesInternalModule()
{
uint8_t protocol = getRequiredProtocol(INTERNAL_MODULE);
@@ -498,6 +601,14 @@ bool setupPulsesInternalModule()
}
#endif
void stopPulsesExternalModule()
{
if (moduleState[EXTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
extmoduleStop();
moduleState[EXTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
}
}
bool setupPulsesExternalModule()
{
uint8_t protocol = getRequiredProtocol(EXTERNAL_MODULE);
+10 -5
View File
@@ -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 {
@@ -315,8 +314,12 @@ extern TrainerPulsesData trainerPulsesData;
#if defined(HARDWARE_INTERNAL_MODULE)
bool setupPulsesInternalModule();
void stopPulsesInternalModule();
#endif
#if defined(HARDWARE_EXTERNAL_MODULE)
bool setupPulsesExternalModule();
void stopPulsesExternalModule();
#endif
void setupPulsesDSM2();
void setupPulsesCrossfire();
void setupPulsesGhost();
@@ -353,7 +356,9 @@ inline void startPulses()
setupPulsesInternalModule();
#endif
#if defined(HARDWARE_EXTERNAL_MODULE)
setupPulsesExternalModule();
#endif
#if defined(HARDWARE_EXTRA_MODULE)
extramodulePpmStart();
+7 -7
View File
@@ -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
@@ -108,7 +108,7 @@ class PwmPxxBitTransport: public PulsesBuffer<pulse_duration_t, 200> {
void addTail()
{
// rest min value is 18000 - 200 * 48 = 8400 (4.2ms)
*(ptr - 1) += rest;
*(ptr - 1) = 60000;
}
};
-2
View File
@@ -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
+29 -5
View File
@@ -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<int SIZE>
class FakeTaskStack
{
@@ -146,6 +158,7 @@ template<int SIZE>
{
return (uint32_t)(simuTimerMicros() / 1000);
}
#elif defined(RTOS_COOS)
#ifdef __cplusplus
extern "C" {
@@ -155,7 +168,7 @@ template<int SIZE>
}
#endif
#define RTOS_MS_PER_TICK ((CFG_CPU_FREQ / CFG_SYSTICK_FREQ) / (CFG_CPU_FREQ / 1000)) // RTOS timer tick length in ms (currently 2)
#define RTOS_MS_PER_TICK (1000 / CFG_SYSTICK_FREQ) // RTOS timer tick length in ms (currently 1 for STM32, 2 for others)
typedef OS_TID RTOS_TASK_HANDLE;
typedef OS_MutexID RTOS_MUTEX_HANDLE;
@@ -230,7 +243,18 @@ template<int SIZE>
#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<int SIZE>
class TaskStack
+4 -4
View File
@@ -53,11 +53,11 @@ void preModelLoad()
}
pauseMixerCalculations();
#if defined(INTMODULE_PWR_GPIO)
INTERNAL_MODULE_OFF();
#if defined(HARDWARE_INTERNAL_MODULE)
stopPulsesInternalModule();
#endif
#if defined(EXTMODULE_PWR_GPIO)
EXTERNAL_MODULE_OFF();
#if defined(HARDWARE_EXTERNAL_MODULE)
stopPulsesExternalModule();
#endif
stopTrainer();
+1 -1
View File
@@ -148,7 +148,7 @@ endif()
if(MULTIMODULE)
add_definitions(-DMULTIMODULE)
set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/mlink.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
endif()
if(CROSSFIRE)
@@ -124,7 +124,7 @@ void auxSerialInit(unsigned int mode, unsigned int protocol)
break;
case UART_MODE_SBUS_TRAINER:
auxSerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
auxSerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // USART_WordLength_9b due to parity bit
AUX_SERIAL_POWER_ON();
break;
@@ -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
@@ -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
@@ -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
+11 -1
View File
@@ -1107,7 +1107,9 @@ OPTIMIZE("O0") SD_Error SD_WaitReadOperation(uint32_t timeout)
delay_ms(1);
timeout--;
}
#if !defined(BOOT)
TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_read, (TransferError << 8) + (DMAEndOfTransfer << 1) + TransferEnd);
#endif
DMAEndOfTransfer = 0;
@@ -1117,7 +1119,9 @@ OPTIMIZE("O0") SD_Error SD_WaitReadOperation(uint32_t timeout)
delay_ms(1);
timeout--;
}
#if !defined(BOOT)
TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_read, -1);
#endif
if (StopCondition == 1) {
errorstatus = SD_StopTransfer();
@@ -1332,8 +1336,10 @@ OPTIMIZE("O0") SD_Error SD_WaitWriteOperation(uint32_t timeout)
delay_ms(1);
timeout--;
}
#if !defined(BOOT)
TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_write, (TransferError << 8) + (DMAEndOfTransfer << 1) + TransferEnd);
#endif
DMAEndOfTransfer = 0;
timeout = 100;
@@ -1342,7 +1348,9 @@ OPTIMIZE("O0") SD_Error SD_WaitWriteOperation(uint32_t timeout)
delay_ms(1);
timeout--;
}
#if !defined(BOOT)
TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_write, -1);
#endif
if (StopCondition == 1) {
errorstatus = SD_StopTransfer();
@@ -1474,7 +1482,9 @@ OPTIMIZE("O0") void SD_ProcessIRQ(void)
SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
#if !defined(BOOT)
TRACE_SD_CARD_EVENT((TransferError != SD_OK), sd_irq, TransferError);
#endif
}
/**
+1
View File
@@ -246,6 +246,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
+1
View File
@@ -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);
+2 -5
View File
@@ -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();
@@ -381,7 +378,7 @@ enum Analogs {
SLIDER_LAST = SLIDER_FIRST + NUM_SLIDERS - 1,
TX_VOLTAGE,
#if defined(PCBX12S)
MOUSE1, // TODO why after voltage?
MOUSE1, // after voltage because previous ones come from SPI on X12S
MOUSE2,
#endif
NUM_ANALOGS
+31 -13
View File
@@ -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();
}
+9 -2
View File
@@ -420,9 +420,9 @@
#define AUX_SERIAL_USART_IRQn USART3_IRQn
#define AUX_SERIAL_DMA_Stream_RX DMA1_Stream1
#define AUX_SERIAL_DMA_Channel_RX DMA_Channel_4
#define AUX_SERIAL_PWR_GPIO GPIOA
#define AUX_SERIAL_PWR_GPIO_PIN GPIO_Pin_15 // PB.00
#if defined(RADIO_TX16S)
#define AUX_SERIAL_PWR_GPIO GPIOA
#define AUX_SERIAL_PWR_GPIO_PIN GPIO_Pin_15 // PA.15
#define TRAINER_BATTERY_COMPARTMENT // allows serial port TTL trainer
#endif
#else
@@ -905,6 +905,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)
+3 -13
View File
@@ -141,29 +141,19 @@ static void LCD_NRSTConfig(void)
GPIO_Init(LCD_GPIO_NRST, &GPIO_InitStructure);
}
// TODO delay function
static void delay3(uint32_t nCount)
{
uint32_t index = 0;
for(index = (1000 * 100 * nCount); index != 0; --index)
{
__asm("nop\n");
}
}
static void lcd_reset(void)
{
#if defined(RADIO_T18) // T18 screen has issues if NRST is ever brought low
NRST_HIGH();
#else
NRST_HIGH();
delay3(1);
delay_ms(1);
NRST_LOW(); // RESET();
delay3(20);
delay_ms(20);
NRST_HIGH();
delay3(30);
delay_ms(30);
#endif
}
@@ -1,16 +1,16 @@
/**
******************************************************************************
* @file startup_stm32f40_41xxx.s
* @file startup_stm32f42_43xx.s
* @author MCD Application Team
* @version V1.3.0
* @date 08-November-2013
* @brief STM32F40xxx/41xxx Devices vector table for RIDE7 toolchain.
* @brief STM32F42xxx/43xxx Devices vector table for RIDE7 toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Configure the clock system and the external SRAM mounted on
* STM324xG-EVAL board to be used as data memory (optional,
* STM32F4xG-EVAL board to be used as data memory (optional,
* to be enabled by user)
* - Branches to main in the C library (which eventually
* calls main()).
@@ -37,7 +37,7 @@
*/
.syntax unified
.cpu cortex-m3
.cpu cortex-m4
.fpu softvfp
.thumb
@@ -69,9 +69,9 @@ defined in linker script */
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
bl pwrResetHandler /*jump to WDT reset handler where soft power control pin is turned on as soon as possible */
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
bl pwrResetHandler /* jump to WDT reset handler where soft power control pin is turned on as soon as possible */
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
@@ -113,7 +113,7 @@ LoopPaintMainStack:
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call C++ constructors for static objects */
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
@@ -34,6 +34,7 @@ static void telemetryInitDirPin()
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
+2
View File
@@ -63,6 +63,7 @@ elseif(PCB STREQUAL X9D+)
option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF)
option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON)
set(FLAVOUR x9d+2019)
set(LUA_EXPORT lua_export_x9d+2019)
set(CPU_TYPE STM32F4)
set(CPU_TYPE_FULL STM32F407xE) # for size report
set(LINKER_SCRIPT targets/taranis/stm32f4_flash.ld)
@@ -449,6 +450,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)
+2 -1
View File
@@ -111,6 +111,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);
@@ -346,4 +347,4 @@ void initJackDetect(void)
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(JACK_DETECT_GPIO, &GPIO_InitStructure);
}
#endif
#endif
+1 -1
View File
@@ -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();
+53 -16
View File
@@ -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();
@@ -98,17 +98,18 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us, bool i
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->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (inverted ? 0 : EXTMODULE_TIMER_OUTPUT_POLARITY);
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;
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);
@@ -214,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);
@@ -257,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
@@ -285,34 +297,54 @@ 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;
#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;
// 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
}
// 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 +405,19 @@ 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_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();
}
+7
View File
@@ -2185,4 +2185,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_
@@ -42,21 +42,23 @@ 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
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
INTMODULE_TIMER->EGR = 1;
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
break;
}
#endif
@@ -97,17 +99,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->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->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 +158,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()
+58 -25
View File
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
#include "mixer_scheduler.h"
RTOS_TASK_HANDLE menusTaskId;
RTOS_DEFINE_STACK(menusStack, MENUS_STACK_SIZE);
@@ -65,13 +66,30 @@ 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
// case PROTOCOL_CHANNELS_PPM:
case PROTOCOL_CHANNELS_PXX1_PULSES:
#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;
}
@@ -96,6 +114,11 @@ TASK_FUNCTION(mixerTask)
{
s_pulses_paused = true;
mixerSchedulerInit();
#if !defined(PCBSKY9X)
mixerSchedulerStart();
#endif
while (true) {
#if defined(SBUS_TRAINER)
// SBUS trainer
@@ -110,7 +133,18 @@ 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
#if !defined(PCBSKY9X)
// re-enable trigger
mixerSchedulerEnableTrigger();
#endif
#if defined(SIMU)
if (pwrCheck() == e_power_off) {
@@ -122,29 +156,22 @@ 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();
DEBUG_TIMER_START(debugTimerMixer);
RTOS_LOCK_MUTEX(mixerMutex);
doMixerCalculations();
#if defined(PCBSKY9X)
sendSynchronousPulses(1 << EXTERNAL_MODULE);
#else
sendSynchronousPulses((1 << INTERNAL_MODULE) | (1 << EXTERNAL_MODULE));
#endif
doMixerPeriodicUpdates();
DEBUG_TIMER_START(debugTimerMixerCalcToUsage);
DEBUG_TIMER_SAMPLE(debugTimerMixerIterval);
RTOS_UNLOCK_MUTEX(mixerMutex);
@@ -173,7 +200,13 @@ 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 defined(DEBUG)
if (timeout)
serialPrint("mix sched timeout!");
#endif
}
}
}
+19
View File
@@ -184,6 +184,25 @@ 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);
}
}
break;
#if defined(LUA)
default:
if (luaInputTelemetryFifo && luaInputTelemetryFifo->hasSpace(telemetryRxBufferCount-2) ) {
+3 -3
View File
@@ -99,15 +99,15 @@ const uint32_t CROSSFIRE_BAUDRATES[] = {
115200,
};
const uint8_t CROSSFIRE_PERIODS[] = {
4,
4,
16,
};
#if SPORT_MAX_BAUDRATE < 400000 || defined(DEBUG)
#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 4000 /* us; 250 Hz */
#endif
#define CROSSFIRE_TELEM_MIRROR_BAUDRATE 115200
+80 -9
View File
@@ -43,12 +43,19 @@ enum
GHOST_ID_TOTAL_LATENCY = 0x0007, // Tx-side total latency
GHOST_ID_VTX_FREQ = 0x0008, // Vtx Frequency (in MHz)
GHOST_ID_VTX_POWER = 0x0009, // Vtx Power (in mW)
GHOST_ID_VTX_CHAN = 0x000a, // Vtx Channel
GHOST_ID_VTX_BAND = 0x000b, // Vtx Band
GHOST_ID_VTX_CHAN = 0x000A, // Vtx Channel
GHOST_ID_VTX_BAND = 0x000B, // Vtx Band
GHOST_ID_PACK_VOLTS = 0x000c, // Battery Pack Voltage
GHOST_ID_PACK_AMPS = 0x000d, // Battery Pack Current
GHOST_ID_PACK_MAH = 0x000e, // Battery Pack mAh consumed
GHOST_ID_PACK_VOLTS = 0x000C, // Battery Pack Voltage
GHOST_ID_PACK_AMPS = 0x000D, // Battery Pack Current
GHOST_ID_PACK_MAH = 0x000E, // Battery Pack mAh consumed
GHOST_ID_GPS_LAT = 0x000F, // GPS Latitude
GHOST_ID_GPS_LONG = 0x0010, // GPS Longitude
GHOST_ID_GPS_ALT = 0x0011, // GPS Altitude
GHOST_ID_GPS_HDG = 0x0012, // GPS Heading
GHOST_ID_GPS_GSPD = 0x0013, // GPS Ground Speed
GHOST_ID_GPS_SATS = 0x0014 // GPS Satellite Count
};
const GhostSensor ghostSensors[] = {
@@ -70,6 +77,13 @@ const GhostSensor ghostSensors[] = {
{GHOST_ID_PACK_AMPS, ZSTR_CURR, UNIT_AMPS, 2},
{GHOST_ID_PACK_MAH, ZSTR_CAPACITY, UNIT_MAH, 0},
{GHOST_ID_GPS_LAT, ZSTR_GPS, UNIT_GPS_LATITUDE, 0},
{GHOST_ID_GPS_LONG, ZSTR_GPS, UNIT_GPS_LONGITUDE, 0},
{GHOST_ID_GPS_GSPD, ZSTR_GSPD, UNIT_KMH, 1},
{GHOST_ID_GPS_HDG, ZSTR_HDG, UNIT_DEGREE, 3},
{GHOST_ID_GPS_ALT, ZSTR_ALT, UNIT_METERS, 0},
{GHOST_ID_GPS_SATS, ZSTR_SATELLITES, UNIT_RAW, 0},
{0x00, NULL, UNIT_RAW, 0},
};
@@ -88,7 +102,11 @@ void processGhostTelemetryValue(uint8_t index, int32_t value)
return;
const GhostSensor * sensor = getGhostSensor(index);
setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, sensor->id, 0, 0, value, sensor->unit, sensor->precision);
uint16_t id = sensor->id;
if (id == GHOST_ID_GPS_LONG) {
id = GHOST_ID_GPS_LAT;
}
setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, id, 0, 0, value, sensor->unit, sensor->precision);
}
void processGhostTelemetryValueString(const GhostSensor * sensor, const char * str)
@@ -105,16 +123,19 @@ bool checkGhostTelemetryFrameCRC()
return (crc == telemetryRxBuffer[len + 1]);
}
// hifirst
uint16_t getTelemetryValue_u16(uint8_t index)
{
return (telemetryRxBuffer[index] << 8) | telemetryRxBuffer[index + 1];
}
// lofirst
uint16_t getTelemetryValue_u16le(uint8_t index)
{
return (telemetryRxBuffer[index + 1] << 8) | telemetryRxBuffer[index];
}
// hifirst
uint32_t getTelemetryValue_s32(uint8_t index)
{
uint32_t val = 0;
@@ -123,6 +144,15 @@ uint32_t getTelemetryValue_s32(uint8_t index)
return val;
}
// lofirst
uint32_t getTelemetryValue_s32le(uint8_t index)
{
uint32_t val = 0;
for (int i = 0; i < 4; ++i)
val <<= 8, val |= telemetryRxBuffer[index + 3 - i];
return val;
}
void processGhostTelemetryFrame()
{
if (!checkGhostTelemetryFrameCRC()) {
@@ -132,6 +162,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);
}
break;
case GHST_DL_LINK_STAT:
{
#if defined(BLUETOOTH)
@@ -213,15 +256,40 @@ void processGhostTelemetryFrame()
case GHST_DL_PACK_STAT: {
#if defined(BLUETOOTH)
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
}
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
}
#endif
processGhostTelemetryValue(GHOST_ID_PACK_VOLTS, getTelemetryValue_u16le(3));
processGhostTelemetryValue(GHOST_ID_PACK_AMPS, getTelemetryValue_u16le(5));
processGhostTelemetryValue(GHOST_ID_PACK_MAH, getTelemetryValue_u16le(7) * 10);
break;
}
case GHST_DL_GPS_PRIMARY: {
#if defined(BLUETOOTH)
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
}
#endif
processGhostTelemetryValue(GHOST_ID_GPS_LAT, getTelemetryValue_s32le(3) / 10);
processGhostTelemetryValue(GHOST_ID_GPS_LONG, getTelemetryValue_s32le(7) / 10);
processGhostTelemetryValue(GHOST_ID_GPS_ALT, (int16_t) getTelemetryValue_u16le(11));
break;
}
case GHST_DL_GPS_SECONDARY: {
#if defined(BLUETOOTH)
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
}
#endif
processGhostTelemetryValue(GHOST_ID_GPS_HDG, getTelemetryValue_u16le(5) / 10);
// ground speed is passed via GHST as cm/s, converted to km/h for OpenTx
processGhostTelemetryValue(GHOST_ID_GPS_GSPD, (getTelemetryValue_u16le(3) * 36 + 50) / 100);
processGhostTelemetryValue(GHOST_ID_GPS_SATS, telemetryRxBuffer[7]);
break;
}
}
}
@@ -272,6 +340,9 @@ void ghostSetDefault(int index, uint8_t id, uint8_t subId)
const GhostSensor * sensor = getGhostSensor(id);
if (sensor) {
TelemetryUnit unit = sensor->unit;
if (unit == UNIT_GPS_LATITUDE || unit == UNIT_GPS_LONGITUDE) {
unit = UNIT_GPS;
}
uint8_t prec = min<uint8_t>(2, sensor->precision);
telemetrySensor.init(sensor->name, unit, prec);
}
+3 -1
View File
@@ -44,6 +44,8 @@
#define GHST_DL_VTX_STAT 0x22
#define GHST_DL_PACK_STAT 0x23
#define GHST_DL_MENU_DESC 0x24
#define GHST_DL_GPS_PRIMARY 0x25
#define GHST_DL_GPS_SECONDARY 0x26
#define GHST_RC_CTR_VAL_12BIT 0x7C0 // 0x3e0 << 1
#define GHST_RC_CTR_VAL_8BIT 0x7C
@@ -113,7 +115,7 @@ enum GhostTelemetryBaudrates
};
#endif
#define GHOST_BAUDRATE 400000
#define GHOST_PERIOD 4
#define GHOST_PERIOD 4000 /* us */
enum GhostLineFlags
{
+161
View File
@@ -0,0 +1,161 @@
/*
* Copyright (C) OpenTX
*
* 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"
struct MLinkSensor
{
const uint16_t id;
const char * name;
const TelemetryUnit unit;
const uint8_t precision;
};
const MLinkSensor mlinkSensors[] = {
{MLINK_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 1},
{MLINK_VOLTAGE, ZSTR_VFAS, UNIT_VOLTS, 1},
{MLINK_CURRENT, ZSTR_CURR, UNIT_AMPS, 1},
{MLINK_VARIO, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 1},
{MLINK_SPEED, ZSTR_SPEED, UNIT_KMH, 1},
{MLINK_RPM, ZSTR_RPM, UNIT_RPMS, 0},
{MLINK_TEMP, ZSTR_TEMP1, UNIT_CELSIUS, 1},
{MLINK_HEADING, ZSTR_HDG, UNIT_DEGREE, 1},
{MLINK_ALT, ZSTR_ALT , UNIT_METERS, 0},
{MLINK_FUEL, ZSTR_FUEL, UNIT_PERCENT, 0},
{MLINK_CAPACITY, ZSTR_CAPACITY, UNIT_MAH, 0},
{MLINK_FLOW, ZSTR_FLOW, UNIT_MILLILITERS, 0},
{MLINK_DISTANCE, ZSTR_DIST, UNIT_KM, 1},
{MLINK_LQI, ZSTR_RSSI, UNIT_RAW, 0},
{MLINK_LOSS, ZSTR_LOSS, UNIT_RAW, 0},
{MLINK_TX_RSSI, ZSTR_TX_RSSI, UNIT_RAW, 0},
{MLINK_TX_LQI, ZSTR_TX_QUALITY, UNIT_RAW, 0},
};
const MLinkSensor * getMLinkSensor(uint16_t id)
{
for (const MLinkSensor * sensor = mlinkSensors; sensor->id; sensor++) {
if (id == sensor->id)
return sensor;
}
return nullptr;
}
void processMLinkPacket(const uint8_t * packet)
{
const uint8_t * data = packet + 2;
// Multi telem
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_TX_RSSI, 0, 0, (packet[0] * 100) / 31, UNIT_RAW, 0);
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_TX_LQI, 0, 0, packet[1], UNIT_RAW, 0);
// M-Link telem
if (data[0] == 0x13) { // Telemetry type RX-9
for (uint8_t i = 1; i < 5; i += 3) { //2 sensors per packet
int32_t val = (int16_t )(data[i + 2] << 8 | data[i + 1]);
val = val >> 1; // remove alarm flag
uint8_t adress = (data[i] & 0xF0) >> 4;
switch (data[i] & 0x0F) {
case MLINK_VOLTAGE:
if ((data[i] & 0xF0) == 0x00){
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_RX_VOLTAGE, 0, adress, val, UNIT_VOLTS, 1);
}
else {
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_VOLTAGE, 0, adress, val, UNIT_VOLTS, 1);
}
break;
case MLINK_CURRENT:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_CURRENT, 0, adress, val, UNIT_AMPS, 1);
break;
case MLINK_VARIO:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_VARIO, 0, adress, val, UNIT_METERS_PER_SECOND, 1);
break;
case MLINK_SPEED:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_SPEED, 0, adress, val, UNIT_KMH, 1);
break;
case MLINK_RPM:
if (val < 0) {
val = -val * 10;
}
else {
val = val * 100;
}
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_RPM, 0, adress, val, UNIT_RPMS, 0);
break;
case MLINK_TEMP:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_TEMP, 0, adress, val, UNIT_CELSIUS, 1);
break;
case MLINK_HEADING:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_HEADING, 0, adress, val, UNIT_DEGREE, 1);
break;
case MLINK_ALT:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_ALT, 0, adress, val, UNIT_METERS, 0);
break;
case MLINK_FUEL:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_FUEL, 0, adress, val, UNIT_PERCENT, 0);
break;
case MLINK_CAPACITY:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_CAPACITY, 0, adress, val, UNIT_MAH, 0);
break;
case MLINK_FLOW:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_FLOW, 0, adress, val, UNIT_MILLILITERS, 0);
break;
case MLINK_DISTANCE:
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_DISTANCE, 0, adress, val, UNIT_KM, 1);
break;
case MLINK_LQI:
uint8_t mlinkRssi = data[i + 1] >> 1;
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_LQI, 0, 0, mlinkRssi, UNIT_RAW, 0);
telemetryData.rssi.set(mlinkRssi);
if (mlinkRssi > 0) {
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
break;
}
}
}
else if (packet[2] == 0x03) { // Telemetry type RX-5
uint16_t mlinkRssi = (packet[4] * 100) / 35;
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_LQI, 0, 0, mlinkRssi, UNIT_RAW, 0);
telemetryData.rssi.set(mlinkRssi);
if (mlinkRssi > 0) {
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
setTelemetryValue(PROTOCOL_TELEMETRY_MLINK, MLINK_LOSS, 0, 0, packet[7], UNIT_RAW, 0);
}
}
void mlinkSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance)
{
TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index];
telemetrySensor.id = id;
telemetrySensor.subId = subId;
telemetrySensor.instance = instance;
const MLinkSensor * sensor = getMLinkSensor(id);
if (sensor) {
TelemetryUnit unit = sensor->unit;
uint8_t prec = min<uint8_t>(2, sensor->precision);
telemetrySensor.init(sensor->name, unit, prec);
if (unit == UNIT_RPMS) {
telemetrySensor.custom.ratio = 1;
telemetrySensor.custom.offset = 1;
}
}
else {
telemetrySensor.init(id);
}
storageDirty(EE_MODEL);
}
+47
View File
@@ -0,0 +1,47 @@
/*
* 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.
*/
#pragma once
enum {
MLINK_VOLTAGE = 1,
MLINK_CURRENT = 2,
MLINK_VARIO = 3,
MLINK_SPEED = 4,
MLINK_RPM = 5,
MLINK_TEMP = 6,
MLINK_HEADING = 7,
MLINK_ALT = 8,
MLINK_FUEL = 9,
MLINK_LQI = 10,
MLINK_CAPACITY = 11,
MLINK_FLOW = 12,
MLINK_DISTANCE = 13,
MLINK_RX_VOLTAGE = 16, // out of range ID for specific RxBt treatment
MLINK_LOSS = 17, // out of range ID for handling number of loss
MLINK_TX_RSSI = 18, // out of range ID for handling Telemetry RSSi reported by multi
MLINK_TX_LQI = 19, // out of range ID for handling Telemetry LQI reported by multi
};
void processMLinkTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount);
void mlinkSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance);
// Used by multi protocol
void processMLinkPacket(const uint8_t *packet);
+14 -125
View File
@@ -42,6 +42,7 @@ enum MultiPacketTypes : uint8_t
FlyskyIBusTelemetryAC,
MultiRxChannels,
HottTelemetry,
MLinkTelemetry
};
enum MultiBufferState : uint8_t
@@ -63,7 +64,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 +74,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 +106,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 +116,6 @@ MultiModuleStatus& getMultiModuleStatus(uint8_t)
return multiModuleStatus;
}
MultiModuleSyncStatus& getMultiSyncStatus(uint8_t)
{
return multiSyncStatus;
}
uint8_t getMultiBindStatus(uint8_t)
{
return multiBindStatus;
@@ -254,23 +243,14 @@ 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 !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());
status.update(refreshRate, inputLag);
#if defined(DEBUG)
serialPrint("MP ADJ: R %d, L %04d", refreshRate, inputLag);
#endif
}
@@ -379,6 +359,13 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module)
TRACE("[MP] Received HoTT telemetry len %d < 14", len);
break;
case MLinkTelemetry:
if (len > 6)
processMLinkPacket(data);
else
TRACE("[MP] Received M-Link telemetry len %d < 6", len);
break;
case FrSkyHubTelemetry:
if (len >= 4)
frskyDProcessPacket(data);
@@ -434,104 +421,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()) {
-22
View File
@@ -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;
+84
View File
@@ -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)
@@ -375,3 +376,86 @@ OutputTelemetryBuffer outputTelemetryBuffer __DMA;
#if defined(LUA)
Fifo<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE> * 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();
TRACE("[SYNC] update rate = %dus; lag = %dus",refreshRate,currentLag);
}
uint16_t ModuleSyncStatus::getAdjustedRefreshRate()
{
int16_t lag = currentLag;
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;
}
currentLag -= newRefreshRate - refreshRate;
TRACE("[SYNC] mod rate = %dus; lag = %dus",newRefreshRate,currentLag);
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
}
+30
View File
@@ -33,6 +33,7 @@
#include "hitec.h"
#include "hott.h"
#include "multi.h"
#include "mlink.h"
#endif
#if defined(MULTIMODULE) || defined(AFHDS3)
#include "flysky_ibus.h"
@@ -289,4 +290,33 @@ extern Fifo<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE> * luaInputTelemetryFifo;
void processPXX2Frame(uint8_t module, const uint8_t *frame);
// Module pulse synchronization
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_
@@ -559,6 +559,10 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui
case PROTOCOL_TELEMETRY_HOTT:
hottSetDefault(index, id, subId, instance);
break;
case PROTOCOL_TELEMETRY_MLINK:
mlinkSetDefault(index, id, subId, instance);
break;
#endif
#if defined(LUA)
+3
View File
@@ -98,6 +98,8 @@ ISTR(INPUTNAMES);
#if defined(MULTIMODULE)
ISTR(MULTI_PROTOCOLS);
ISTR(MULTI_POWER);
ISTR(MULTI_TELEMETRY_MODE);
ISTR(MULTI_WBUS_MODE);
#endif
#if defined(BLUETOOTH)
@@ -707,6 +709,7 @@ const char STR_BIND_OK[] = TR_BIND_OK;
const char STR_MULTI_CUSTOM[] = TR_MULTI_CUSTOM;
const char STR_MULTI_RFTUNE[] = TR_MULTI_RFTUNE;
const char STR_MULTI_RFPOWER[] = TR_MULTI_RFPOWER;
const char STR_MULTI_WBUS[] = TR_MULTI_WBUS;
const char STR_MULTI_TELEMETRY[] = TR_MULTI_TELEMETRY;
const char STR_MULTI_VIDFREQ[] = TR_MULTI_VIDFREQ;
const char STR_MULTI_OPTION[] = TR_MULTI_OPTION;
+3
View File
@@ -161,6 +161,8 @@ extern const char STR_R9M_PXX2_RF_PROTOCOLS[];
extern const char STR_DSM_PROTOCOLS[];
extern const char STR_MULTI_PROTOCOLS[];
extern const char STR_MULTI_POWER[];
extern const char STR_MULTI_TELEMETRY_MODE[];
extern const char STR_MULTI_WBUS_MODE[];
extern const char STR_SPORT_MODES[];
#if defined(AFHDS3)
@@ -403,6 +405,7 @@ extern const char STR_MULTI_OPTION[];
extern const char STR_MULTI_VIDFREQ[];
extern const char STR_MULTI_RFTUNE[];
extern const char STR_MULTI_RFPOWER[];
extern const char STR_MULTI_WBUS[];
extern const char STR_MULTI_TELEMETRY[];
extern const char STR_MULTI_AUTOBIND[];
extern const char STR_DISABLE_CH_MAP[];
+5 -1
View File
@@ -261,7 +261,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metr.\0""Imper.", "Metrické""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -640,6 +640,7 @@
#define TR_RECEIVER "Přijímač"
#define TR_MULTI_RFTUNE TR(INDENT "Ladění frek", INDENT "Jemné ladění frek. RF")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetrie"
#define TR_MULTI_VIDFREQ TR(INDENT "Freq. videa", INDENT "Frekvence videa")
#define TR_RFPOWER "Výkon RF"
@@ -1382,3 +1383,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -264,7 +264,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\012")
#define TR_VUNITSSYSTEM TR("Metrik""Imper.", "Metrisch\0 ""Imperial\0 ")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -642,6 +642,7 @@
#define TR_RECEIVER "Empfänger"
#define TR_MULTI_RFTUNE TR(INDENT "RF Freq.", INDENT "RF Freq. Feintuning")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR(INDENT "Vid. Freq.", INDENT "Video Frequenz")
#define TR_RFPOWER "RF Power"
@@ -1389,3 +1390,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -264,7 +264,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -641,6 +641,7 @@
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -1386,3 +1387,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -261,7 +261,7 @@
#define LEN_VUNITSSYSTEM "\010"
#define TR_VUNITSSYSTEM "Métrico\0""Imperial"
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -643,6 +643,7 @@
#define TR_RECEIVER "Receptor"
#define TR_MULTI_RFTUNE TR("Sint.freq.", "RF Freq. sint.fina")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetría"
#define TR_MULTI_VIDFREQ TR("Freq.vídeo", "Frecuencia vídeo")
#define TR_RFPOWER "RF Power"
@@ -1385,3 +1386,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -282,7 +282,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -659,6 +659,7 @@
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -1393,3 +1394,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -284,7 +284,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\012")
#define TR_VUNITSSYSTEM TR("Métr.\0""Impér.", "Métriques\0""Impériales")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -662,6 +662,7 @@
#define TR_RECEIVER "Récept."
#define TR_MULTI_RFTUNE TR(INDENT "Ajust.fréq", INDENT "Ajustement fréq.")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Télémétrie"
#define TR_MULTI_VIDFREQ TR(INDENT "Fréq. vidéo", INDENT "Fréquence vidéo")
#define TR_RFPOWER TR("Puiss. RF", "Puissance RF")
@@ -1410,3 +1411,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+20 -16
View File
@@ -285,7 +285,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\011")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metriche\0""Imperiali")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -463,7 +463,7 @@
#define TR_TTRIM TR("Trim Mot.", INDENT "Trim Motore")
#define TR_TTRIM_SW TR("T-Trim-Sw", INDENT "Trim switch")
#define TR_BEEPCTR TR("Beep al c.", "Beep al centro")
#define TR_USE_GLOBAL_FUNCS "Usa Funz. Globali"
#define TR_USE_GLOBAL_FUNCS TR("Funz. Glob.", "Usa Funz. Globali")
#if defined(PCBSKY9X) && defined(REVX)
#define TR_OUTPUT_TYPE INDENT "Uscita"
#endif
@@ -661,6 +661,7 @@
#define TR_RECEIVER "Ricevente"
#define TR_MULTI_RFTUNE TR("Tune RF", "Tune fine Freq. RF")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetria"
#define TR_MULTI_VIDFREQ TR("Freq. video", "Frequenza video")
#define TR_RFPOWER "Potenza RF"
@@ -872,28 +873,28 @@
#define TR_FLASH_EXTERNAL_MODULE TR("Prog. modulo est.", "Programma modulo esterno")
#define TR_FLASH_INTERNAL_MULTI TR("Prog. MULTI int.", "Programma MULTI interno")
#define TR_FLASH_EXTERNAL_MULTI TR("Prog. MULTI est.", "Programma MULTI esterno")
#define TR_FIRMWARE_UPDATE_ERROR TR(INDENT "Errore agg. FW",INDENT "Errore aggiornamento firmware")
#define TR_FIRMWARE_UPDATE_ERROR TR(INDENT "Errore agg. FW",INDENT "Errore aggiornamento firmware")
#define TR_FIRMWARE_UPDATE_SUCCESS "Aggiornamento" BREAKSPACE "riuscito"
#define TR_WRITING "Scrittura..."
#define TR_CONFIRM_FORMAT "Confermi formattazione?"
#define TR_INTERNALRF "Modulo interno"
#define TR_WRITING "Scrittura..."
#define TR_CONFIRM_FORMAT "Confermi formattazione?"
#define TR_INTERNALRF "Modulo interno"
#define TR_INTERNAL_MODULE TR("Modulo int.", "Modulo interno")
#define TR_EXTERNAL_MODULE TR("Modulo est.", "Modulo esterno")
#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX richiede aggiornamento"
#define TR_TELEMETRY_DISABLED TR("Telem. off", "Telem. disabilitata")
#define TR_MORE_OPTIONS_AVAILABLE "Altre opzioni assenti"
#define TR_NO_MODULE_INFORMATION "Nessuna info del modulo"
#define TR_EXTERNALRF "Modulo esterno"
#define TR_FAILSAFE "Modo failsafe"
#define TR_FAILSAFESET TR(INDENT "FAILSAFE", INDENT "IMPOSTAZIONI FAILSAFE")
#define TR_EXTERNALRF "Modulo esterno"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Modo failsafe")
#define TR_FAILSAFESET TR(INDENT "FAILSAFE", INDENT "IMPOSTAZIONI FAILSAFE")
#define TR_REG_ID "Reg. ID"
#define TR_OWNER_ID "Owner ID"
#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "Hold"
#define TR_HOLD "Hold"
#define TR_HOLD_UPPERCASE "HOLD"
#define TR_NONE "None"
#define TR_NONE "None"
#define TR_NONE_UPPERCASE "NONE"
#define TR_MENUSENSOR "SENSORE"
#define TR_MENUSENSOR "SENSORE"
#define TR_POWERMETER_PEAK "Picco"
#define TR_POWERMETER_POWER "Potenza"
#define TR_POWERMETER_ATTN "Att."
@@ -935,7 +936,7 @@
#define TR_SPEAKER INDENT "Speaker"
#define TR_BUZZER INDENT "Buzzer"
#define TR_BYTES "Bytes"
#define TR_MODULE_BIND "[Bind]"
#define TR_MODULE_BIND TR("[Bnd]","[Bind]")
#define TR_POWERMETER_ATTN_NEEDED "Attenuatore necessario"
#define TR_PXX2_SELECT_RX "Seleziona RX..."
#define TR_PXX2_DEFAULT "<default>"
@@ -947,8 +948,8 @@
#define TR_RECEIVER_RESET "Resetto RX?"
#define TR_SHARE "Condividere"
#define TR_BIND "Bind"
#define TR_REGISTER TR("Reg", "Registrare")
#define TR_MODULE_RANGE "[Range]"
#define TR_REGISTER TR("Reg", "Registrare")
#define TR_MODULE_RANGE TR("[Rng]","[Range]")
#define TR_RECEIVER_OPTIONS TR("OPZIONI RX", "OPZIONI RICEVENTE")
#define TR_DEL_BUTTON BUTTON(TR("Canc.", "Cancella"))
#define TR_RESET_BTN "[Reset]"
@@ -971,7 +972,7 @@
#define TR_TOPLCDTIMER "Timer LCD Sup."
#define TR_UNIT "Unita"
#define TR_TELEMETRY_NEWSENSOR INDENT "Aggiungi nuovo sensore"
#define TR_CHANNELRANGE INDENT "Numero Canali"
#define TR_CHANNELRANGE TR(INDENT "Num Canali", INDENT "Numero Canali")
#define TR_AFHDS3_RX_FREQ TR("Freq. RX", "Frequenza RX")
#define TR_AFHDS3_ONE_TO_ONE_TELEMETRY TR("Unicast/Tel.", "Unicast/Telemetria")
#define TR_AFHDS3_ONE_TO_MANY "Multicast"
@@ -1403,3 +1404,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -265,7 +265,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Mtrsch""Engels", "Metrisch\0 ""Engels\0 ")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -647,6 +647,7 @@
#define TR_RECEIVER "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -1395,3 +1396,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -282,7 +282,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010") /*8 decimal*/
#define TR_VUNITSSYSTEM TR("Metr. ""Imper.", "Metryczn""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -660,6 +660,7 @@
#define TR_RECEIVER INDENT "Receiver"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -1402,3 +1403,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -278,7 +278,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -662,6 +662,7 @@
#define TR_SYNCMENU "Sync [MENU]"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -1401,3 +1402,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+5 -1
View File
@@ -279,7 +279,7 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metri.""Imper.", "Metriska""Imperial")
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0"
#define TR_VTELEMUNIT "-\0 ""V\0 ""A\0 ""mA\0""kts""m/s""f/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""mW\0""dB\0""rpm""g\0 ""@\0 ""rad""ml\0""fOz""mlm""Hz\0""mS\0""uS\0""km\0"
#define STR_V (STR_VTELEMUNIT+1)
#define STR_A (STR_VTELEMUNIT+4)
@@ -660,6 +660,7 @@
#define TR_SYNCMENU "Synk [MENU]"
#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune")
#define TR_MULTI_RFPOWER "RF power"
#define TR_MULTI_WBUS "Output"
#define TR_MULTI_TELEMETRY "Telemetry"
#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency")
#define TR_RFPOWER "RF Power"
@@ -1402,3 +1403,6 @@
#define ZSTR_SERVO_VOLTAGE "SrvV"
#define ZSTR_SERVO_TEMPERATURE "SrvT"
#define ZSTR_SERVO_STATUS "SrvS"
#define ZSTR_LOSS "Loss"
#define ZSTR_SPEED "Spd "
#define ZSTR_FLOW "Flow"
+7 -1
View File
@@ -134,7 +134,13 @@
#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""Futaba\0""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""Height\0""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 ""Kyosho\0""RadLink""ExpLRS\0""Realacc""OMP\0 ""M-Link\0""Wfly 2\0""E016Hv2"
#define LEN_MULTI_POWER "\005"
#define TR_MULTI_POWER "10mW\0""25mW\0""50mW\0""100mW""200mW""300mW""500mW""1W\0 ""2W\0 "
#define TR_MULTI_POWER "1.6mW""2.0mW""2.5mW""3.2mW""4.0mW""5.0mW""6.3mW""7.9mW""10mW\0""13mW\0""16mW\0""20mW\0""25mW\0""32mW\0""40mW\0""50mW\0"
#define LEN_MULTI_WBUS_MODE "\004"
#define TR_MULTI_WBUS_MODE "WBUS""PPM\0"
#define LEN_MULTI_TELEMETRY_MODE "\007"
#define TR_MULTI_TELEMETRY_MODE "Off\0 ""On\0 ""Off+Aux""On+Aux\0"
#define LEN_AFHDS3_PROTOCOLS "\x008"
#define TR_AFHDS3_PROTOCOLS "PWM/IBUS""PWM/SBUS""PPM/IBUS""PPM/SBUS"