Merge with latest 2.3
This commit is contained in:
@@ -382,6 +382,7 @@ set(SRC
|
||||
strhelpers.cpp
|
||||
switches.cpp
|
||||
mixer.cpp
|
||||
mixer_scheduler.cpp
|
||||
stamp.cpp
|
||||
timers.cpp
|
||||
trainer.cpp
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@ const char * const unitsFilenames[] = {
|
||||
"hertz",
|
||||
"ms",
|
||||
"us",
|
||||
"spare4",
|
||||
"km",
|
||||
"spare5",
|
||||
"spare6",
|
||||
"spare7",
|
||||
|
||||
+5
-5
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) ) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user