diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index c899632af..3ce9836fb 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -160,7 +160,8 @@ QString ModuleData::protocolToString(unsigned protocol) "FrSky ACCESS R9M Lite", "FrSky ACCESS R9M Lite Pro", "FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)", - "AFHDS3" + "AFHDS3", + "ImmersionRC Ghost" }; return CHECK_IN_ARRAY(strings, protocol); @@ -221,6 +222,7 @@ int ModuleData::getMaxChannelCount() case PULSES_XJT_LITE_X16: case PULSES_PXX_XJT_X16: case PULSES_CROSSFIRE: + case PULSES_GHOST: case PULSES_SBUS: case PULSES_PPM: return 16; diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index d3e851879..e22c167e3 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -59,6 +59,7 @@ enum PulsesProtocol { PULSES_XJT_LITE_D8, PULSES_XJT_LITE_LR12, PULSES_AFHDS3, + PULSES_GHOST, PULSES_PROTOCOL_LAST }; diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h index 29d5b0b93..bb55b5687 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.h +++ b/companion/src/firmwares/opentx/opentxeeprom.h @@ -96,7 +96,7 @@ class ProtocolsConversionTable: public ConversionTable addConversion(PULSES_ACCESS_R9M, val++); addConversion(PULSES_PXX_R9M_LITE, val++); addConversion(PULSES_ACCESS_R9M_LITE, val++); - addConversion(PULSES_PXX_R9M_LITE_PRO, val++); + addConversion(PULSES_GHOST, val++); addConversion(PULSES_ACCESS_R9M_LITE_PRO, val++); addConversion(PULSES_SBUS, val++); @@ -104,6 +104,7 @@ class ProtocolsConversionTable: public ConversionTable addConversion(PULSES_XJT_LITE_X16, val); addConversion(PULSES_XJT_LITE_D8, val); addConversion(PULSES_XJT_LITE_LR12, val++); + if (version >= 219) { addConversion(PULSES_AFHDS3, val++); } diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 75aab7b64..910271eca 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -760,6 +760,7 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) case PULSES_MULTIMODULE: case PULSES_CROSSFIRE: case PULSES_AFHDS3: + case PULSES_GHOST: return true; case PULSES_ACCESS_R9M: return IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess")); diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index 0a7e7eada..6048b8641 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -84,6 +84,12 @@ QString SensorData::unitString() const return tr("V"); case UNIT_MILLILITERS_PER_MINUTE: return tr("ml/minute"); + case UNIT_HERZ: + return tr("Hertz"); + case UNIT_MS: + return tr("mS"); + case UNIT_US: + return tr("uS"); default: return ""; } diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index 3f995ea3e..7b0a5f368 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -94,10 +94,10 @@ class SensorData { UNIT_MILLILITERS, UNIT_FLOZ, UNIT_MILLILITERS_PER_MINUTE, - UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE, - UNIT_SPARE1, - UNIT_SPARE2, - UNIT_SPARE3, + UNIT_HERZ, + UNIT_MS, + UNIT_US, + UNIT_MAX = UNIT_US, UNIT_SPARE4, UNIT_SPARE5, UNIT_SPARE6, diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 898596a6c..df6792ff8 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -424,6 +424,7 @@ void ModulePanel::update() max_rx_num = 20; break; case PULSES_CROSSFIRE: + case PULSES_GHOST: mask |= MASK_CHANNELS_RANGE; module.channelsCount = 16; break; diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp index bd56876c6..3dc945f5d 100644 --- a/companion/src/modelprinter.cpp +++ b/companion/src/modelprinter.cpp @@ -212,7 +212,7 @@ QString ModelPrinter::printModule(int idx) str << printLabelValue(tr("Delay"), QString("%1us").arg(module.ppm.delay)); } else { - if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_SBUS)) { + if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_GHOST || module.protocol == PULSES_SBUS)) { str << printLabelValue(tr("Receiver"), QString::number(module.modelId)); } if (module.protocol == PULSES_MULTIMODULE) { diff --git a/radio/sdcard/horus/WIDGETS/Ghost/img/background.png b/radio/sdcard/horus/WIDGETS/Ghost/img/background.png new file mode 100644 index 000000000..887c022fa Binary files /dev/null and b/radio/sdcard/horus/WIDGETS/Ghost/img/background.png differ diff --git a/radio/sdcard/horus/WIDGETS/Ghost/main.lua b/radio/sdcard/horus/WIDGETS/Ghost/main.lua new file mode 100644 index 000000000..dfaef17c9 --- /dev/null +++ b/radio/sdcard/horus/WIDGETS/Ghost/main.lua @@ -0,0 +1,88 @@ +---- ######################################################################### +---- # # +---- # 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. # +---- # # +---- ######################################################################### + +local backgroundBitmap +local offsetX +local offsetY +local sensors = {} + +local options = { + { "VTX", BOOL, 0 }, +} + +local function getValues(wgt) + if wgt.options.VTX == 0 then + sensors[1] = string.format("%s", getValue("RFMD")) + sensors[2] = string.format("%d Hz", getValue("FRat")) + sensors[3] = string.format("%d %%", getValue("RQly")) + if (getValue("TPWR") == 0) then + sensors[4] = "Range" + else + sensors[4] = string.format("%d mW", getValue("TPWR")) + end + else + sensors[1] = string.format("%s", getValue("VBan")) + sensors[2] = string.format("%dMHz", getValue("VFrq")) + sensors[3] = string.format("CH: %d", getValue("VChn")) + sensors[4] = string.format("%d mW", getValue("VPwr")) + end +end + +local function create(zone, options) + local wgt = { zone=zone, options=options} + backgroundBitmap = Bitmap.open("/WIDGETS/Ghost/img/background.png") + offsetX = (wgt.zone.w - 178) / 2 + offsetY = (wgt.zone.h - 148) / 2 + return wgt +end + +local function update(wgt, options) + wgt.options = options +end + +local function background(wgt) +end + +function refresh(wgt) + -- runs onty on large enough zone + if wgt.zone.w < 180 or wgt.zone.h < 145 then + return + end + + if backgroundBitmap ~= nil then + lcd.drawBitmap(backgroundBitmap, wgt.zone.x + offsetX, wgt.zone.y + offsetY) + end + + if getRSSI() ~= 0 then + getValues(wgt) + + -- RF Mode/Band + lcd.drawText(wgt.zone.x + offsetX + 75, wgt.zone.y + offsetY + 2, sensors[1], CENTER + DBLSIZE) + + -- Frame rate / Frequency + lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 35, sensors[2], CENTER + DBLSIZE) + + -- RSSI / Channel + lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 70, sensors[3], CENTER + DBLSIZE) + + -- Transmit power + lcd.drawText(wgt.zone.x + offsetX + 85, wgt.zone.y + offsetY + 105, sensors[4], CENTER + DBLSIZE) + end + +end + +return { name="Ghost", options=options, create=create, update=update, refresh=refresh, background=background } \ No newline at end of file diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 989457f92..47a1fed2a 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -54,6 +54,7 @@ option(MODULE_PROTOCOL_FLEX "Add support for non certified FLEX modules" OFF) option(MODULE_PROTOCOL_D8 "Add support for D8 modules" ON) option(FRSKY_RELEASE "Used to build FrSky released firmware" OFF) option(TBS_RELEASE "Used to build TBS released firmware" OFF) +option(IMRC_RELEASE "Used to build IMRC released firmware" OFF) option(ALLOW_TRAINER_MULTI "Allow multi trainer" OFF) # since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags. @@ -348,6 +349,10 @@ if(TBS_RELEASE) add_definitions(-DTBS_RELEASE) endif() +if(IMRC_RELEASE) + add_definitions(-DIMRC_RELEASE) +endif() + if(FRSKY_RELEASE) add_definitions(-DFRSKY_RELEASE) set(POPUP_LEVEL 3) diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index c8417568d..702ec044e 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -158,9 +158,9 @@ const char * const unitsFilenames[] = { "ml", "founce", "mlpm", - "spare1", - "spare2", - "spare3", + "hertz", + "ms", + "us", "spare4", "spare5", "spare6", diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 512ac301f..52ddc5854 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -270,7 +270,8 @@ enum TelemetryProtocol PROTOCOL_TELEMETRY_HOTT, PROTOCOL_TELEMETRY_MULTIMODULE, PROTOCOL_TELEMETRY_AFHDS3, - PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_AFHDS3, + PROTOCOL_TELEMETRY_GHOST, + PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_GHOST, PROTOCOL_TELEMETRY_LUA }; @@ -304,10 +305,10 @@ enum TelemetryUnit { UNIT_MILLILITERS, UNIT_FLOZ, UNIT_MILLILITERS_PER_MINUTE, - UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE, - UNIT_SPARE1, - UNIT_SPARE2, - UNIT_SPARE3, + UNIT_HERTZ, + UNIT_MS, + UNIT_US, + UNIT_MAX = UNIT_US, UNIT_SPARE4, UNIT_SPARE5, UNIT_SPARE6, diff --git a/radio/src/gui/480x272/radio_hardware.cpp b/radio/src/gui/480x272/radio_hardware.cpp index 6b395290e..419fedbf5 100644 --- a/radio/src/gui/480x272/radio_hardware.cpp +++ b/radio/src/gui/480x272/radio_hardware.cpp @@ -126,7 +126,7 @@ void onHardwareAntennaSwitchConfirm(const char * result) #define EXTERNAL_ANTENNA_ROW #endif -#if defined(CROSSFIRE) +#if (defined(CROSSFIRE) || defined(GHOST)) #define MAX_BAUDRATE_ROW 0 #else #define MAX_BAUDRATE_ROW HIDDEN_ROW diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index a2d486193..8824d6a57 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -162,7 +162,7 @@ enum { ITEM_RADIO_HARDWARE_CAPACITY_CALIB, #endif -#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 +#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000 ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE, #endif @@ -278,7 +278,7 @@ void onHardwareAntennaSwitchConfirm(const char * result) #define TX_CAPACITY_MEASUREMENT_ROWS #endif -#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 +#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000 #define MAX_BAUD_ROWS 0, #else #define MAX_BAUD_ROWS @@ -544,7 +544,7 @@ void menuRadioHardware(event_t event) break; #endif -#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 +#if (defined(CROSSFIRE) || defined(GHOST)) && SPORT_MAX_BAUDRATE < 400000 case ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE: lcdDrawTextAlignedLeft(y, STR_MAXBAUDRATE); lcdDrawNumber(HW_SETTINGS_COLUMN2, y, CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate], attr|LEFT); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 3b9bb3421..d832bc1c4 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -584,6 +584,14 @@ bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType) } } +bool areModulesConflicting(int intModuleType, int extModuleType) +{ + if (intModuleType == MODULE_TYPE_ISRM_PXX2) + return (extModuleType == MODULE_TYPE_GHOST); + + return false; +} + #if defined(HARDWARE_INTERNAL_MODULE) bool isInternalModuleAvailable(int moduleType) { @@ -605,7 +613,7 @@ bool isInternalModuleAvailable(int moduleType) if (moduleType == MODULE_TYPE_ISRM_PXX2) { #if defined(PXX2) && defined(INTERNAL_MODULE_PXX2) - return true; + return !areModulesConflicting(moduleType, g_model.moduleData[EXTERNAL_MODULE].type); #endif } @@ -620,9 +628,6 @@ bool isInternalModuleAvailable(int moduleType) bool isExternalModuleAvailable(int moduleType) { - if (moduleType == MODULE_TYPE_R9M_LITE_PRO_PXX1) - return false; - #if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) if (isModuleTypeR9MLite(moduleType) || moduleType == MODULE_TYPE_XJT_LITE_PXX2) return false; @@ -657,6 +662,11 @@ bool isExternalModuleAvailable(int moduleType) return false; #endif +#if !defined(GHOST) + if (moduleType == MODULE_TYPE_GHOST) + return false; +#endif + #if !defined(DSM2) if (moduleType == MODULE_TYPE_DSM2) return false; @@ -673,6 +683,9 @@ bool isExternalModuleAvailable(int moduleType) #endif #if defined(HARDWARE_INTERNAL_MODULE) + if (areModulesConflicting(g_model.moduleData[INTERNAL_MODULE].type, moduleType)) + return false; + if (isTrainerUsingModuleBay() || (isModuleUsingSport(EXTERNAL_MODULE, moduleType) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type))) return false; #endif @@ -697,6 +710,11 @@ bool isRfProtocolAvailable(int protocol) return false; } #endif +#if defined(GHOST) + if (protocol != MODULE_SUBTYPE_PXX1_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST) { + return false; + } +#endif #if !defined(MODULE_PROTOCOL_D8) if (protocol == MODULE_SUBTYPE_PXX1_ACCST_D8) { return false; @@ -726,6 +744,10 @@ bool isTelemetryProtocolAvailable(int protocol) return false; } + if ( protocol== PROTOCOL_TELEMETRY_GHOST) { + return false; + } + #if !defined(MULTIMODULE) if (protocol == PROTOCOL_TELEMETRY_SPEKTRUM || protocol == PROTOCOL_TELEMETRY_FLYSKY_IBUS || protocol == PROTOCOL_TELEMETRY_MULTIMODULE) { return false; diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index f5d7e1f51..2c89a24ed 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -175,7 +175,7 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) else return 0; } - else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleSBUS(moduleIdx)) { + else if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleGhost(moduleIdx) || isModuleSBUS(moduleIdx)) { return 0; } else { diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 3ee1bf1ae..544417dda 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1981,6 +1981,9 @@ const luaR_value_entry opentxConstants[] = { {"UNIT_MILLILITERS", UNIT_MILLILITERS }, {"UNIT_FLOZ", UNIT_FLOZ }, {"UNIT_MILLILITERS_PER_MINUTE", UNIT_MILLILITERS_PER_MINUTE }, + {"UNIT_HERTZ", UNIT_HERTZ }, + {"UNIT_MS", UNIT_MS }, + {"UNIT_US", UNIT_US }, {"UNIT_HOURS", UNIT_HOURS }, {"UNIT_MINUTES", UNIT_MINUTES }, {"UNIT_SECONDS", UNIT_SECONDS }, diff --git a/radio/src/options.h b/radio/src/options.h index 741c38b77..f2b3c8369 100644 --- a/radio/src/options.h +++ b/radio/src/options.h @@ -29,6 +29,9 @@ static const char * const options[] = { #if defined(CROSSFIRE) "crossfire", #endif +#if defined(GHOST) + "ghost", +#endif #if !defined(MODULE_PROTOCOL_D8) "eu", #endif diff --git a/radio/src/pulses/ghost.cpp b/radio/src/pulses/ghost.cpp new file mode 100755 index 000000000..6c5ec243b --- /dev/null +++ b/radio/src/pulses/ghost.cpp @@ -0,0 +1,89 @@ +/* + * 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" + +// Range for pulses (channels output) is [-1024:+1024] +uint8_t createGhostChannelsFrame(uint8_t * frame, int16_t * pulses) +{ + static uint8_t lastGhostFrameId = GHST_UL_RC_CHANS_HS4_5TO8; + uint8_t ghostUpper4Offset = 0; + + switch (lastGhostFrameId) { + case GHST_UL_RC_CHANS_HS4_5TO8: + ghostUpper4Offset = 0; + break; + case GHST_UL_RC_CHANS_HS4_9TO12: + ghostUpper4Offset = 4; + break; + case GHST_UL_RC_CHANS_HS4_13TO16: + ghostUpper4Offset = 8; + break; + } + + uint8_t * buf = frame; + *buf++ = GHST_ADDR_MODULE; + *buf++ = GHST_UL_RC_CHANS_SIZE; + uint8_t * crc_start = buf; + *buf++ = lastGhostFrameId; + + // first 4 high speed, 12 bit channels (11 relevant bits with openTx) + uint32_t bits = 0; + uint8_t bitsavailable = 0; + for (int i = 0; i < 4; i++) { + uint32_t value = limit(0, GHST_RC_CTR_VAL_12BIT + (((pulses[i]) << 3) / 5), 2 * GHST_RC_CTR_VAL_12BIT); + bits |= value << bitsavailable; + bitsavailable += GHST_CH_BITS_12; + while (bitsavailable >= 8) { + *buf++ = bits; + bits >>= 8; + bitsavailable -= 8; + } + } + + // second 4 lower speed, 8 bit channels + for (int i = 4; i < 8; ++i) { + *buf++ = limit(0, GHST_RC_CTR_VAL_8BIT + (((pulses[i + ghostUpper4Offset]) >> 1) / 5), 2 * GHST_RC_CTR_VAL_8BIT); + } + + *buf++ = crc8(crc_start, GHST_UL_RC_CHANS_SIZE - 1); + + switch (lastGhostFrameId) { + case GHST_UL_RC_CHANS_HS4_5TO8: + lastGhostFrameId = GHST_UL_RC_CHANS_HS4_9TO12; + break; + case GHST_UL_RC_CHANS_HS4_9TO12: + lastGhostFrameId = GHST_UL_RC_CHANS_HS4_13TO16; + break; + case GHST_UL_RC_CHANS_HS4_13TO16: + lastGhostFrameId = GHST_UL_RC_CHANS_HS4_5TO8; + break; + } + + return buf - frame; +} + +void setupPulsesGhost() +{ + if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) { + uint8_t * pulses = extmodulePulsesData.ghost.pulses; + extmodulePulsesData.ghost.length = createGhostChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]); + } +} diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h index 4f391243a..0ddf2477a 100644 --- a/radio/src/pulses/modules_constants.h +++ b/radio/src/pulses/modules_constants.h @@ -29,11 +29,11 @@ enum ModuleType { MODULE_TYPE_DSM2, MODULE_TYPE_CROSSFIRE, MODULE_TYPE_MULTIMODULE, - MODULE_TYPE_R9M_PXX1, - MODULE_TYPE_R9M_PXX2, - MODULE_TYPE_R9M_LITE_PXX1, - MODULE_TYPE_R9M_LITE_PXX2, - MODULE_TYPE_R9M_LITE_PRO_PXX1, // Doesn't exist + MODULE_TYPE_R9M_PXX1, // R9M + MODULE_TYPE_R9M_PXX2, // R9M ACCESS + MODULE_TYPE_R9M_LITE_PXX1, //R9MLite + MODULE_TYPE_R9M_LITE_PXX2, //R9MLP + MODULE_TYPE_GHOST, // Replaces MODULE_TYPE_R9M_LITE_PRO_PXX1 which doesn't exist MODULE_TYPE_R9M_LITE_PRO_PXX2, MODULE_TYPE_SBUS, MODULE_TYPE_XJT_LITE_PXX2, diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index e13eaf2fb..2d56bf564 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -33,6 +33,7 @@ #endif #define CROSSFIRE_CHANNELS_COUNT 16 +#define GHOST_CHANNELS_COUNT 12 #if defined(MULTIMODULE) // When using packed, the pointer in here end up not being aligned, which clang and gcc complain about @@ -150,6 +151,18 @@ inline bool isModuleCrossfire(uint8_t idx) } #endif +#if defined(GHOST) +inline bool isModuleGhost(uint8_t idx) +{ + return idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST; +} +#else +inline bool isModuleGhost(uint8_t idx) +{ + return false; +} +#endif + #if defined(PCBSKY9X) inline bool isExtraModule(uint8_t idx) { @@ -178,7 +191,7 @@ inline bool isModulePPM(uint8_t moduleIdx) inline bool isModuleTypeR9MNonAccess(uint8_t type) { - return type == MODULE_TYPE_R9M_PXX1 || type == MODULE_TYPE_R9M_LITE_PXX1 || type == MODULE_TYPE_R9M_LITE_PRO_PXX1; + return type == MODULE_TYPE_R9M_PXX1 || type == MODULE_TYPE_R9M_LITE_PXX1; } inline bool isModuleR9MNonAccess(uint8_t idx) @@ -218,7 +231,7 @@ inline bool isModuleR9MLiteNonPro(uint8_t idx) inline bool isModuleTypeR9MLitePro(uint8_t type) { - return type == MODULE_TYPE_R9M_LITE_PRO_PXX1 || type == MODULE_TYPE_R9M_LITE_PRO_PXX2; + return type == MODULE_TYPE_R9M_LITE_PRO_PXX2; } inline bool isModuleTypeR9MLite(uint8_t type) @@ -384,6 +397,8 @@ inline int8_t sentModuleChannels(uint8_t idx) { if (isModuleCrossfire(idx)) return CROSSFIRE_CHANNELS_COUNT; + else if (isModuleGhost(idx)) + return GHOST_CHANNELS_COUNT; else if (isModuleMultimodule(idx) && !isModuleMultimoduleDSM2(idx)) return 16; else if (isModuleSBUS(idx)) @@ -528,7 +543,7 @@ inline bool isTelemAllowedOnBind(uint8_t moduleIndex) return true; } - if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M_PXX1 || g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M_LITE_PRO_PXX1) { + if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M_PXX1) { if (isModuleR9M_LBT(EXTERNAL_MODULE)) return g_model.moduleData[EXTERNAL_MODULE].pxx.power < R9M_LBT_POWER_200_16CH_NOTELEM; else diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index f669f5fdb..d6833bfe9 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -133,7 +133,6 @@ uint8_t getRequiredProtocol(uint8_t module) #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) case MODULE_TYPE_R9M_LITE_PXX1: - case MODULE_TYPE_R9M_LITE_PRO_PXX1: protocol = PROTOCOL_CHANNELS_PXX1_SERIAL; break; @@ -193,6 +192,12 @@ uint8_t getRequiredProtocol(uint8_t module) break; #endif +#if defined(GHOST) + case MODULE_TYPE_GHOST: + protocol = PROTOCOL_CHANNELS_GHOST; + break; +#endif + default: protocol = PROTOCOL_CHANNELS_NONE; break; @@ -243,6 +248,12 @@ void enablePulsesExternalModule(uint8_t protocol) break; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + EXTERNAL_MODULE_ON(); + break; +#endif + #if defined(PXX2) && defined(EXTMODULE_USART) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: extmoduleInvertedSerialStart(PXX2_HIGHSPEED_BAUDRATE); @@ -332,6 +343,13 @@ bool setupPulsesExternalModule(uint8_t protocol) return true; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + setupPulsesGhost(); + scheduleNextMixerCalculation(EXTERNAL_MODULE, GHOST_PERIOD); + return true; +#endif + #if defined(MULTIMODULE) case PROTOCOL_CHANNELS_MULTIMODULE: setupPulsesMultiExternalModule(); diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index f92629f6e..5bff463f6 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -237,6 +237,12 @@ PACK(struct CrossfirePulsesData { uint8_t length; }); +#define GHOST_FRAME_MAXLEN 16 +PACK(struct GhostPulsesData { + uint8_t pulses[GHOST_FRAME_MAXLEN]; + uint8_t length; +}); + union InternalModulePulsesData { #if defined(PXX1) #if defined(INTMODULE_USART) @@ -286,6 +292,8 @@ union ExternalModulePulsesData { PpmPulsesData ppm; CrossfirePulsesData crossfire; + + GhostPulsesData ghost; } __ALIGNED(4); /* The __ALIGNED keyword is required to align the struct inside the modulePulsesData below, @@ -310,6 +318,7 @@ bool setupPulsesInternalModule(); bool setupPulsesExternalModule(); void setupPulsesDSM2(); void setupPulsesCrossfire(); +void setupPulsesGhost(); void setupPulsesMultiExternalModule(); void setupPulsesMultiInternalModule(); void setupPulsesSbus(); @@ -364,7 +373,8 @@ enum ChannelsProtocols { PROTOCOL_CHANNELS_SBUS, PROTOCOL_CHANNELS_PXX2_LOWSPEED, PROTOCOL_CHANNELS_PXX2_HIGHSPEED, - PROTOCOL_CHANNELS_AFHDS3 + PROTOCOL_CHANNELS_AFHDS3, + PROTOCOL_CHANNELS_GHOST }; inline void stopPulses() diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index ad28e4037..a61d4a29a 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -40,6 +40,8 @@ #define DISPLAY_VERSION "-radiomaster" #elif defined(TBS_RELEASE) #define DISPLAY_VERSION "-tbs" +#elif defined(IMRC_RELEASE) +#define DISPLAY_VERSION "-imrc" #else #define DISPLAY_VERSION #endif diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 3a8846dfc..b6c6b639e 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -14,6 +14,7 @@ option(PPM "PPM TX Module" ON) option(DSM2 "DSM2 TX Module" ON) option(SBUS "SBUS TX Module" ON) option(CROSSFIRE "Crossfire TX Module" ON) +option(GHOST "Ghost TX Module" ON) option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON) option(DEBUG_INTERRUPTS "Count interrupts" OFF) option(DEBUG_LATENCY "Debug latency" OFF) @@ -175,6 +176,18 @@ if(MULTIMODULE OR AFHDS3) set(SRC ${SRC} telemetry/flysky_ibus.cpp ) endif() +if(GHOST) + add_definitions(-DGHOST) + set(PULSES_SRC + ${PULSES_SRC} + ghost.cpp + ) + set(SRC + ${SRC} + telemetry/ghost.cpp + ) +endif() + add_definitions(-DCPUARM) add_definitions(-DGPS) add_definitions(-DBOLD_FONT -DBATTGRAPH -DTHRTRACE) diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 525c8a4ad..68d20e733 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -48,6 +48,7 @@ if (PCB STREQUAL X10) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(BLUETOOTH ON) add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT) + add_definitions(-DRADIO_X10E) elseif (PCBREV STREQUAL T16) set(FLAVOUR t16) set(LUA_EXPORT lua_export_t16) diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 9c04aeb21..47a40ae02 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -368,6 +368,12 @@ void extmoduleSendNextFrame() break; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + sportSendBuffer(extmodulePulsesData.ghost.pulses, extmodulePulsesData.ghost.length); + break; +#endif + default: EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; break; diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 0910f156e..a5b6a4acd 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -321,6 +321,12 @@ void extmoduleSendNextFrame() break; #endif +#if defined(GHOST) + case PROTOCOL_CHANNELS_GHOST: + sportSendBuffer(extmodulePulsesData.ghost.pulses, extmodulePulsesData.ghost.length); + break; +#endif + default: EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; break; diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index e9dcfac45..16e120784 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -76,7 +76,7 @@ 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_NONE) + 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) diff --git a/radio/src/telemetry/ghost.cpp b/radio/src/telemetry/ghost.cpp new file mode 100755 index 000000000..1146b9555 --- /dev/null +++ b/radio/src/telemetry/ghost.cpp @@ -0,0 +1,216 @@ +/* + * 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" + +const char * const ghstRfProfileValue[GHST_RF_PROFILE_COUNT] = { "Auto", "Norm", "Race", "Pure", "Long" }; +const char * const ghstVtxBandName[GHST_VTX_BAND_COUNT] = { "- - -" , "IRC", "Race", "BandE", "BandB", "BandA" }; + +struct GhostSensor +{ + const uint16_t id; + const char * name; + const TelemetryUnit unit; + const uint8_t precision; +}; + +// telemetry sensors ID +enum +{ + GHOST_ID_RX_RSSI = 0x0001, // Rx-side RSSI + GHOST_ID_RX_LQ = 0x0002, // Rx-side link quality + GHOST_ID_RX_SNR = 0x0003, // Rx-side signal to noise + GHOST_ID_FRAME_RATE = 0x0004, // Tx-side frame rate + GHOST_ID_TX_POWER = 0x0005, // Tx-side power output + GHOST_ID_RF_MODE = 0x0006, // Tx-side frame rate + 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 + +}; + +const GhostSensor ghostSensors[] = { + {GHOST_ID_RX_RSSI, ZSTR_RSSI, UNIT_DB, 0}, + {GHOST_ID_RX_LQ, ZSTR_RX_QUALITY, UNIT_PERCENT, 0}, + {GHOST_ID_RX_SNR, ZSTR_RX_SNR, UNIT_DB, 0}, + + {GHOST_ID_FRAME_RATE, ZSTR_FRAME_RATE, UNIT_RAW, 0}, + {GHOST_ID_TX_POWER, ZSTR_TX_POWER, UNIT_MILLIWATTS, 0}, + {GHOST_ID_RF_MODE, ZSTR_RF_MODE, UNIT_TEXT, 0}, + {GHOST_ID_TOTAL_LATENCY, ZSTR_TOTAL_LATENCY, UNIT_RAW, 0}, + + {GHOST_ID_VTX_FREQ, ZSTR_VTX_FREQ, UNIT_RAW, 0}, + {GHOST_ID_VTX_POWER, ZSTR_VTX_PWR, UNIT_RAW, 0}, + {GHOST_ID_VTX_CHAN, ZSTR_VTX_CHAN, UNIT_RAW, 0}, + {GHOST_ID_VTX_BAND, ZSTR_VTX_BAND, UNIT_TEXT, 0}, + + {0x00, NULL, UNIT_RAW, 0}, +}; + +const GhostSensor *getGhostSensor(uint8_t id) +{ + for (const GhostSensor * sensor = ghostSensors; sensor->id; sensor++) { + if (id == sensor->id) + return sensor; + } + return nullptr; +} + +void processGhostTelemetryValue(uint8_t index, int32_t value) +{ + if (!TELEMETRY_STREAMING()) + return; + + const GhostSensor * sensor = getGhostSensor(index); + setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, sensor->id, 0, 0, value, sensor->unit, sensor->precision); +} + +void processGhostTelemetryValueString(const GhostSensor * sensor, const char * str) +{ + int i = 0; + if (TELEMETRY_STREAMING()) { + do { + setTelemetryValue(PROTOCOL_TELEMETRY_GHOST, sensor->id, 0, 0, str[i], UNIT_TEXT, i); + } while (str[i++] != 0); + } +} + +bool checkGhostTelemetryFrameCRC() +{ + uint8_t len = telemetryRxBuffer[1]; + uint8_t crc = crc8(&telemetryRxBuffer[2], len - 1); + return (crc == telemetryRxBuffer[len + 1]); +} + +uint16_t getTelemetryValue_u16(uint8_t index) +{ + return (telemetryRxBuffer[index] << 8) | telemetryRxBuffer[index + 1]; +} + +uint32_t getTelemetryValue_s32(uint8_t index) +{ + uint32_t val = 0; + for (int i = 0; i < 4; ++i) + val <<= 8, val |= telemetryRxBuffer[index + i]; + return val; +} + +void processGhostTelemetryFrame() +{ + if (!checkGhostTelemetryFrameCRC()) { + TRACE("[GS] CRC error"); + return; + } + + uint8_t id = telemetryRxBuffer[2]; + switch(id) { + case GHST_DL_LINK_STAT: + { + uint8_t rssiVal = min(telemetryRxBuffer[3], 100); + uint8_t lqVal = min(telemetryRxBuffer[4], 100); + uint8_t snrVal = min(telemetryRxBuffer[5], 100); + + processGhostTelemetryValue(GHOST_ID_RX_RSSI, rssiVal); + processGhostTelemetryValue(GHOST_ID_RX_LQ, lqVal); + processGhostTelemetryValue(GHOST_ID_RX_SNR, snrVal); + + // give OpenTx the LQ value, not RSSI + if (lqVal) { + telemetryData.rssi.set(lqVal); + telemetryStreaming = TELEMETRY_TIMEOUT10ms; + } + else { + telemetryData.rssi.reset(); + telemetryStreaming = 0; + } + + processGhostTelemetryValue(GHOST_ID_TX_POWER, getTelemetryValue_u16(6)); + processGhostTelemetryValue(GHOST_ID_FRAME_RATE, getTelemetryValue_u16(8)); + processGhostTelemetryValue(GHOST_ID_TOTAL_LATENCY, getTelemetryValue_u16(10)); + uint8_t rfModeEnum = min(telemetryRxBuffer[12], GHST_RF_PROFILE_MAX); + + // RF mode string, one char at a time + const GhostSensor * sensor = getGhostSensor(GHOST_ID_RF_MODE); + const char * rfModeString = ghstRfProfileValue[rfModeEnum]; + processGhostTelemetryValueString(sensor, rfModeString); + break; + } + + case GHST_DL_VTX_STAT: + { + uint8_t vtxBandEnum = min(telemetryRxBuffer[8], GHST_VTX_BAND_MAX); + + const GhostSensor * sensor = getGhostSensor(GHOST_ID_VTX_BAND); + const char * vtxBandString = ghstVtxBandName[vtxBandEnum]; + + processGhostTelemetryValue(GHOST_ID_VTX_FREQ, getTelemetryValue_u16(4)); + processGhostTelemetryValue(GHOST_ID_VTX_POWER, getTelemetryValue_u16(6)); + processGhostTelemetryValue(GHOST_ID_VTX_CHAN, min(telemetryRxBuffer[9], 8)); + processGhostTelemetryValueString(sensor, vtxBandString); + break; + } + } +} + +void processGhostTelemetryData(uint8_t data) +{ + if (telemetryRxBufferCount == 0 && data != GHST_ADDR_RADIO) { + TRACE("[GH] address 0x%02X error", data); + return; + } + + if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + telemetryRxBuffer[telemetryRxBufferCount++] = data; + } + else { + TRACE("[GH] array size %d error", telemetryRxBufferCount); + telemetryRxBufferCount = 0; + } + + if (telemetryRxBufferCount > 4) { + uint8_t length = telemetryRxBuffer[1]; + if (length + 2 == telemetryRxBufferCount) { + processGhostTelemetryFrame(); + telemetryRxBufferCount = 0; + } + } +} + + +void ghostSetDefault(int index, uint8_t id, uint8_t subId) +{ + TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index]; + + telemetrySensor.id = id; + telemetrySensor.instance = subId; + + const GhostSensor * sensor = getGhostSensor(id); + if (sensor) { + TelemetryUnit unit = sensor->unit; + uint8_t prec = min(2, sensor->precision); + telemetrySensor.init(sensor->name, unit, prec); + } + else + telemetrySensor.init(id); + + storageDirty(EE_MODEL); +} diff --git a/radio/src/telemetry/ghost.h b/radio/src/telemetry/ghost.h new file mode 100755 index 000000000..57adb8f96 --- /dev/null +++ b/radio/src/telemetry/ghost.h @@ -0,0 +1,114 @@ +/* + * 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 _GHOST_H_ +#define _GHOST_H_ + +#include +#include "dataconstants.h" + +// Device (destination) address +#define GHST_ADDR_RADIO 0x80 // phase 1 +#define GHST_ADDR_MODULE 0x81 +#define GHST_ADDR_FC 0x82 +#define GHST_ADDR_GOGGLES 0x83 // phase 2 +#define GHST_ADDR_5G_TXCTRL 0x84 // phase 3 +#define GHST_ADDR_5G_TWRSCAN 0x85 +#define GHST_ADDR_5G_RLY 0x86 + +#define GHST_UL_RC_CHANS_HS4_5TO8 0x10 // High Speed 4 channel (12 bits), plus CH5-8 (8 bits) +#define GHST_UL_RC_CHANS_HS4_9TO12 0x11 // High Speed 4 channel (12 bits), plus CH9-12 (8 bits) +#define GHST_UL_RC_CHANS_HS4_13TO16 0x12 // High Speed 4 channel (12 bits), plus CH13-16 (8 bits) +#define GHST_UL_RC_CHANS_SIZE 12 // 1 (type) + 10 (data) + 1 (crc) + +#define GHST_DL_OPENTX_SYNC 0x20 +#define GHST_DL_LINK_STAT 0x21 +#define GHST_DL_VTX_STAT 0x22 + +#define GHST_RC_CTR_VAL_12BIT 0x7C0 // 0x3e0 << 1 +#define GHST_RC_CTR_VAL_8BIT 0x7C + +#define GHST_CH_BITS_12 12 +#define GHST_CH_BITS_8 8 + +enum GhstPowerMode +{ + GHST_PWR_16UW = 0, + GHST_PWR_100UW = 1, + GHST_PWR_1MW = 2, + GHST_PWR_25MW = 3, + GHST_PWR_100MW = 4, + GHST_PWR_200MW = 5, + GHST_PWR_350MW = 6, + GHST_PWR_500MW = 7, + GHST_PWR_600MW = 8, + GHST_PWR_1W = 9, + GHST_PWR_1_5W = 10, + GHST_PWR_2W = 11, + GHST_PWR_3W = 12, + GHST_PWR_4W = 13, + GHST_PWR_COUNT +}; + +enum GhstRFProfile +{ + GHST_RF_PROFILE_Auto = 0, + GHST_RF_PROFILE_Normal = 1, + GHST_RF_PROFILE_Race = 2, + GHST_RF_PROFILE_PureRace = 3, + GHST_RF_PROFILE_LongRange = 4, + GHST_RF_PROFILE_MAX = GHST_RF_PROFILE_LongRange, + GHST_RF_PROFILE_COUNT +}; + +enum GhstVtxBand +{ + GHST_VTX_BAND_Unknown = 0, + GHST_VTX_BAND_Irc = 1, + GHST_VTX_BAND_Race = 2, + GHST_VTX_BAND_BandE = 3, + GHST_VTX_BAND_BandB = 4, + GHST_VTX_BAND_BandA = 5, + GHST_VTX_BAND_MAX = GHST_VTX_BAND_BandA, + GHST_VTX_BAND_COUNT +}; + +void processGhostTelemetryData(uint8_t data); +void ghostSetDefault(int index, uint8_t id, uint8_t subId); + +#if SPORT_MAX_BAUDRATE < 400000 +// For radios which can't support telemetry at high rates, offer baud rate choices +// (modified vs. unmodified radios) +const uint32_t GHOST_BAUDRATES[] = { + 400000, + 115200, +}; +const uint8_t GHOST_PERIODS[] = { + 4, + 16, +}; +#define GHOST_BAUDRATE GHOST_BAUDRATES[g_eeGeneral.telemetryBaudrate] +#define GHOST_PERIOD GHOST_PERIODS[g_eeGeneral.telemetryBaudrate] +#else +#define GHOST_BAUDRATE 400000 +#define GHOST_PERIOD 4 +#endif + +#endif // _GHOST_H_ diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index a5f1af94f..5c5b3f514 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -45,6 +45,13 @@ void processTelemetryData(uint8_t data) } #endif +#if defined(GHOST) + if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) { + processGhostTelemetryData(data); + return; + } +#endif + #if defined(MULTIMODULE) if (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM) { processSpektrumTelemetryData(EXTERNAL_MODULE, data, telemetryRxBuffer, telemetryRxBufferCount); @@ -295,6 +302,16 @@ void telemetryInit(uint8_t protocol) } #endif +#if defined(GHOST) + else if (protocol == PROTOCOL_TELEMETRY_GHOST) { + telemetryPortInit(GHOST_BAUDRATE, TELEMETRY_SERIAL_DEFAULT); +#if defined(LUA) + outputTelemetryBuffer.reset(); +#endif + telemetryPortSetDirectionOutput(); + } +#endif + #if defined(AUX_SERIAL) || defined(PCBSKY9X) else if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) { telemetryPortInit(0, TELEMETRY_SERIAL_DEFAULT); diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index d35198cdc..b03412355 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -23,6 +23,7 @@ #include "frsky.h" #include "crossfire.h" +#include "ghost.h" #include "myeeprom.h" #include "io/frsky_sport.h" @@ -153,6 +154,12 @@ inline uint8_t modelTelemetryProtocol() } #endif +#if defined(GHOST) + if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_GHOST) { + return PROTOCOL_TELEMETRY_GHOST; + } +#endif + if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) { return g_model.telemetryProtocol; } diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp index d94a8471a..abf531b39 100644 --- a/radio/src/telemetry/telemetry_sensors.cpp +++ b/radio/src/telemetry/telemetry_sensors.cpp @@ -526,6 +526,11 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui crossfireSetDefault(index, id, instance); break; #endif +#if defined(GHOST) + case PROTOCOL_TELEMETRY_GHOST: + ghostSetDefault(index, id, instance); + break; +#endif #if defined(MULTIMODULE) || defined(AFHDS3) case PROTOCOL_TELEMETRY_FLYSKY_IBUS: flySkySetDefault(index,id, subId, instance); diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 4e819d439..a01ed39d7 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -260,7 +260,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1350,3 +1350,9 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 4b445d02e..5d0581c18 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -263,7 +263,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" + #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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1357,3 +1357,9 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 5275f9074..1bd2d5671 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -263,7 +263,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1354,3 +1354,9 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 0335e11c1..a9af085b2 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -260,7 +260,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1352,4 +1352,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index c560254f6..3a6944d03 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -281,7 +281,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1360,4 +1360,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index d6096e4f2..b4db92ecc 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -283,7 +283,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1377,4 +1377,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index f848f4662..5cd184b65 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -284,7 +284,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1371,3 +1371,9 @@ #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" #define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index f9801f767..97f90ce11 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -264,7 +264,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1362,4 +1362,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 34fc6a65d..b807f86af 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -281,7 +281,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1369,4 +1369,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index c4c9d15bd..96c61ec56 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -277,7 +277,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" + #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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1358,4 +1358,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 78fde6fa5..c4db808f7 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -278,7 +278,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" +#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 STR_V (STR_VTELEMUNIT+1) #define STR_A (STR_VTELEMUNIT+4) @@ -1369,4 +1369,10 @@ #define ZSTR_CL15 "Cl15" #define ZSTR_CL16 "Cl16" #define ZSTR_CL17 "Cl17" -#define ZSTR_CL18 "Cl18" \ No newline at end of file +#define ZSTR_CL18 "Cl18" +#define ZSTR_FRAME_RATE "FRat" +#define ZSTR_TOTAL_LATENCY "TLat" +#define ZSTR_VTX_FREQ "VFrq" +#define ZSTR_VTX_PWR "VPwr" +#define ZSTR_VTX_CHAN "VChn" +#define ZSTR_VTX_BAND "VBan" \ No newline at end of file diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 32acdcb84..8f13d4cea 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -87,7 +87,7 @@ #endif #define LEN_EXTERNAL_MODULE_PROTOCOLS "\014" -#define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""R9MLP\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite\0 ""AFHDS3" +#define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""GHST\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite\0 ""AFHDS3\0 " #define LEN_INTERNAL_MODULE_PROTOCOLS LEN_EXTERNAL_MODULE_PROTOCOLS #define TR_INTERNAL_MODULE_PROTOCOLS TR_EXTERNAL_MODULE_PROTOCOLS diff --git a/radio/util/tts_en.py b/radio/util/tts_en.py index a914ccf21..7edfa1eec 100755 --- a/radio/util/tts_en.py +++ b/radio/util/tts_en.py @@ -38,6 +38,9 @@ for i, (s, f) in enumerate([("volt", "volt0"), ("volts", "volt1"), ("milliliter", "ml0"), ("milliliters", "ml1"), ("fluid ounce", "founce0"), ("fluid ounces", "founce1"), ("milliliter per minute", "mlpm0"), ("milliliters per minute", "mlpm1"), + ("hertz", "hertz0"), ("hertz", "hertz1"), + ("milisecond", "ms0"), ("miliseconds", "ms1"), + ("microsecond", "us0"), ("microseconds", "us1"), ("hour", "hour0"), ("hours", "hour1"), ("minute", "minute0"), ("minutes", "minute1"), ("second", "second0"), ("seconds", "second1"),