diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index e6c42e288..35b9922fd 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -46,7 +46,6 @@ option(TRACE_LUA_INTERNALS "Turn on traces for Lua internals" OFF) option(FRSKY_STICKS "Reverse sticks for FrSky sticks" OFF) option(NANO "Use nano newlib and binalloc") option(NIGHTLY_BUILD_WARNING "Warn this is a nightly build" OFF) -option(MODULE_R9M_FLEX_FW "Add R9M options for non certified firmwwares" OFF) # since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags. set(FIRMWARE_C_FLAGS "" CACHE STRING "Additional flags for firmware target c compiler (note: all CMAKE_C_FLAGS[_*] are ignored for firmware/bootloader).") @@ -312,10 +311,6 @@ if(NIGHTLY_BUILD_WARNING) add_definitions(-DNIGHTLY_BUILD_WARNING) endif(NIGHTLY_BUILD_WARNING) -if(MODULE_R9M_FLEX_FW) - add_definitions(-DMODULE_R9M_FLEX_FW) -endif() - set(SRC ${SRC} opentx.cpp diff --git a/radio/src/bitfield.h b/radio/src/bitfield.h new file mode 100644 index 000000000..84b3632b5 --- /dev/null +++ b/radio/src/bitfield.h @@ -0,0 +1,51 @@ +/* + * 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 + * + * This file is based on work published at http://www.coranac.com/documents/working-with-bits-and-bitfields + * + * 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 BITFIELD_H +#define BITFIELD_H + +// A set of bitfield handling macros +#define BF_BIT(n) ( 1<<(n) ) +#define BF_BIT_GET(y, mask) ( y & (mask) ) +#define BF_BIT_SET(y, mask) ( y |= (mask) ) +#define BF_BIT_CLEAR(y, mask) ( y &= ~(mask) ) +#define BF_BIT_FLIP(y, mask) ( y ^= (mask) ) +#define BF_SINGLE_BIT_GET(y, i) BF_BIT_GET(y, BF_BIT(i)) +#define BF_SINGLE_BIT_SET(y, i) BF_BIT_SET(y, BF_BIT(i)) + +//! Create a bitmask of length 'len'. +#define BF_BITMASK(len) ( BF_BIT(len)-1 ) + +//! Create a bitfield mask of length 'len' starting at bit 'start'. +#define BF_MASK(start, len) ( BF_BITMASK(len)<<(start) ) + +//! Prepare a bitmask for insertion or combining. +#define BF_PREP(x, start, len) ( ((x)&BF_BITMASK(len)) << (start) ) + +//! Extract a bitfield of length 'len' starting at bit 'start' from 'y'. +#define BF_GET(y, start, len) ( ((y)>>(start)) & BF_BITMASK(len) ) + +//! Insert 'len' bits of 'x 'into 'y', starting at bit 'start' from 'y'. +#define BF_SET(y, x, start, len) \ + ( y= ((y) &~ BF_MASK(start, len)) | BF_PREP(x, start, len) ) + +#endif //BITFIELD_H \ No newline at end of file diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 6b2298f09..7db9f56ea 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -161,7 +161,7 @@ enum MenuModelSetupItems { #endif #define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 0) - #define EXTERNAL_MODULE_MODE_ROWS (isModulePXX(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0 + #define EXTERNAL_MODULE_MODE_ROWS (isModuleXJT(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0 #define CURSOR_ON_CELL (true) #define MODEL_SETUP_MAX_LINES (HEADER_LINE+ITEM_MODEL_SETUP_MAX) @@ -727,7 +727,7 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0); else if (isModuleDSM2(EXTERNAL_MODULE)) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0); - else if (isModuleR9M(EXTERNAL_MODULE)) + else if (isR9ModuleRunning(EXTERNAL_MODULE)) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0)); #if defined(MULTIMODULE) else if (isModuleMultimodule(EXTERNAL_MODULE)) { @@ -1192,13 +1192,7 @@ void menuModelSetup(event_t event) } #endif if (isModuleR9M(moduleIdx)) { - lcdDrawTextAlignedLeft(y, STR_MODULE_TELEMETRY); - if (IS_TELEMETRY_INTERNAL_MODULE()) { - lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL); - } - else { - lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON); - } + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, TR_R9MFLEX_FREQ, BF_GET(g_model.moduleData[EXTERNAL_MODULE].subType, 0, 1), attr); } else if (isModuleSBUS(moduleIdx)) { lcdDrawTextAlignedLeft(y, STR_WARN_BATTVOLTAGE); diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index c48ee4463..5959484da 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -54,6 +54,7 @@ bool isSwitchAvailableInCustomFunctions(int swtch); bool isSwitchAvailableInMixes(int swtch); bool isSwitchAvailableInTimers(int swtch); bool isR9MModeAvailable(int mode); +bool isR9ModuleRunning(int module); bool isModuleAvailable(int module); bool isRfProtocolAvailable(int protocol); bool isTelemetryProtocolAvailable(int protocol); @@ -155,12 +156,12 @@ const mm_protocol_definition *getMultiProtocolDefinition (uint8_t protocol); #define FAILSAFE_ROWS(x) ((isModuleXJT(x) && HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol)) || MULTIMODULE_HASFAILSAFE(x) || isModuleR9M(x)) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW -#define EXTERNAL_MODULE_OPTION_ROW (isModuleR9M(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW) +#define EXTERNAL_MODULE_OPTION_ROW (isR9ModuleRunning(EXTERNAL_MODULE) ? HIDDEN_ROW : isModuleSBUS(EXTERNAL_MODULE) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW) #if defined(PCBXLITE) && !defined(MODULE_R9M_FULLSIZE) #define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9M(EXTERNAL_MODULE)) ? (isModuleR9M_FCC_VARIANT(EXTERNAL_MODULE) ? TITLE_ROW : (uint8_t) 0) : HIDDEN_ROW #else -#define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9M(EXTERNAL_MODULE)) ? (uint8_t) 0 : HIDDEN_ROW +#define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isR9ModuleRunning(EXTERNAL_MODULE)) ? (uint8_t) 0 : HIDDEN_ROW #endif void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags); diff --git a/radio/src/gui/gui_common_arm.cpp b/radio/src/gui/gui_common_arm.cpp index 0fad2f4c4..343103bd6 100644 --- a/radio/src/gui/gui_common_arm.cpp +++ b/radio/src/gui/gui_common_arm.cpp @@ -486,13 +486,18 @@ bool isSourceAvailableInResetSpecialFunction(int index) } } +bool isR9ModuleRunning(int module) +{ +#if defined(SIMU) + return g_model.moduleData[module].type == MODULE_TYPE_R9M && TELEMETRY_STREAMING(); // Simu uses telemetry simu to activate/desactivate R9 +#else + return g_model.moduleData[module].type == MODULE_TYPE_R9M && R9ModuleStreaming; +#endif +} + bool isR9MModeAvailable(int mode) { -#if defined(MODULE_R9M_FLEX_FW) - return mode >= MODULE_SUBTYPE_R9M_EUPLUS; -#else - return mode <= MODULE_SUBTYPE_R9M_EU; -#endif + return mode <= MODULE_SUBTYPE_R9M_EUPLUS; } bool isModuleAvailable(int module) @@ -516,6 +521,9 @@ bool isModuleAvailable(int module) return false; } #endif + if (module == MODULE_TYPE_R9M && g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE) { + return false; + } return true; } @@ -531,6 +539,10 @@ bool isRfProtocolAvailable(int protocol) return false; } #endif + if (protocol != RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M) { + return false; + } + return true; } diff --git a/radio/src/opentx.h b/radio/src/opentx.h index daf616120..0039e0a3f 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -27,6 +27,7 @@ #include #include "definitions.h" #include "opentx_types.h" +#include "bitfield.h" #if defined(STM32) #include "usbd_conf.h" #endif diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index 3c7311988..8b7e047a2 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -184,8 +184,10 @@ enum R9MLBTPowerValues { #else -#define LEN_R9M_REGION "\006" -#define TR_R9M_REGION "FCC\0 ""EU\0 ""868MHz""915MHz" +#define LEN_R9M_REGION "\004" +#define TR_R9M_REGION "FCC\0""EU\0 ""FLEX" +#define LEN_R9MFLEX_FREQ "\006" +#define TR_R9MFLEX_FREQ "868Mhz""915Mhz" #define LEN_R9M_FCC_POWER_VALUES "\006" #define LEN_R9M_LBT_POWER_VALUES "\013" #define TR_R9M_FCC_POWER_VALUES "10 mW\0" "100 mW" "500 mW" "1 W\0" diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index 2ae1adfd8..7cce0f298 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -45,6 +45,7 @@ void Pxx2Pulses::setupFrame(uint8_t port) #if defined(LUA) if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) { + TRACE("SENDING TELEM"); // primID (1 byte) + dataID (2 bytes) + value (4 bytes) for (uint8_t i=0; i<7; i++) { addByte(outputTelemetryBuffer[i]); diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp index 249776c17..e5eb12ff9 100644 --- a/radio/src/telemetry/frsky.cpp +++ b/radio/src/telemetry/frsky.cpp @@ -59,6 +59,11 @@ void processFrskyPXX2Data(uint8_t data) telemetryRxBuffer[telemetryRxBufferCount++] = data; if (telemetryRxBuffer[0] + 3 /* 1 byte for length, 2 bytes for CRC */ == telemetryRxBufferCount) { if (checkPXX2PacketCRC(telemetryRxBuffer)) { + R9ModuleStreaming = TELEMETRY_TIMEOUT10ms; // reset counter only if valid packets are being detected + uint8_t R9Region = (telemetryRxBuffer[3] & 0x30) >> 4; + if (R9Region != 0x04) { + BF_SET(g_model.moduleData[EXTERNAL_MODULE].subType, R9Region, 1, 2); // heading bit holds flex frequency + } if (telemetryRxBuffer[2] & 0x80) { createFrSkyPXX2Sensor(RSSI_ID, telemetryRxBuffer[2] & 0x7f); } @@ -68,7 +73,11 @@ void processFrskyPXX2Data(uint8_t data) if((telemetryRxBuffer[3] & 0x04) == 0) { createFrSkyPXX2Sensor(R9_PWR_ID, (telemetryRxBuffer[3] & 0x03)); } - sportProcessTelemetryPacketWithoutCrc(telemetryRxBuffer + 6 /* LEN, TYPE, RSSI/BAT, TP/SS/FW_T, FW_VER, Data ID */); + + if (telemetryRxBuffer[0] == 0x0c) { + sportProcessTelemetryPacketWithoutCrc(telemetryRxBuffer + 5 /* LEN, TYPE, RSSI/BAT, TP/SS/FW_T, FW_VER, Data ID */); + TRACE("Got TELEM data"); + } } telemetryRxBufferCount = 0; dataState = STATE_DATA_IDLE; diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h index 7b789edeb..2e88e4843 100644 --- a/radio/src/telemetry/frsky.h +++ b/radio/src/telemetry/frsky.h @@ -190,9 +190,10 @@ enum FrSkyDataState { #define BATT_ID 0xf104 #define RAS_ID 0xf105 #define XJT_VERSION_ID 0xf106 +#define R9_PWR_ID 0xf107 #define FUEL_QTY_FIRST_ID 0x0a10 #define FUEL_QTY_LAST_ID 0x0a1f -#define R9_PWR_ID 0xf107 // TODO: *CRITICAL* agree on ID with FrSky, this value is just a placeholder + // Default sensor data IDs (Physical IDs + CRC) diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 96124792c..8fabe7692 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -21,6 +21,7 @@ #include "opentx.h" uint8_t telemetryStreaming = 0; +uint8_t R9ModuleStreaming = 0; uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) uint8_t telemetryRxBufferCount = 0; @@ -120,7 +121,7 @@ void telemetryWakeup() varioWakeup(); } #endif - + #define FRSKY_BAD_ANTENNA() (IS_RAS_VALUE_VALID() && telemetryData.swr.value > 0x33) static tmr10ms_t alarmsCheckTime = 0; @@ -202,7 +203,9 @@ void telemetryInterrupt10ms() wshhStreaming--; } #endif - + if (R9ModuleStreaming > 0) { + R9ModuleStreaming--; + } if (telemetryStreaming > 0) { telemetryStreaming--; } diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 3170bae7f..400a27ed6 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -36,6 +36,7 @@ #endif extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time +extern uint8_t R9ModuleStreaming; // >0 (true) == R9 module is connected and sending data 0 = no data detected for some time #if defined(WS_HOW_HIGH) extern uint8_t wshhStreaming; @@ -130,7 +131,7 @@ inline uint8_t modelTelemetryProtocol() if (!IS_INTERNAL_MODULE_ENABLED() && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M) { return PROTOCOL_TELEMETRY_PXX2; } - + #if defined(MULTIMODULE) if (!IS_INTERNAL_MODULE_ENABLED() && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) { return PROTOCOL_TELEMETRY_MULTIMODULE; diff --git a/radio/src/translations.h b/radio/src/translations.h index 2ec3981dd..4e2191070 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -188,8 +188,9 @@ extern const char STR_OPEN9X[]; #define OFS_VFAILSAFE (OFS_USBMODES + sizeof(TR_USBMODES)) #define OFS_VTRAINERMODES (OFS_VFAILSAFE + sizeof(TR_VFAILSAFE)) #define OFS_TARANIS_PROTOCOLS (OFS_VTRAINERMODES + sizeof(TR_VTRAINERMODES)) - #define OFS_R9M_REGION (OFS_TARANIS_PROTOCOLS + sizeof(TR_TARANIS_PROTOCOLS)) - #define OFS_R9M_FCC_POWER_VALUES (OFS_R9M_REGION + sizeof(TR_R9M_REGION)) + #define OFS_R9M_REGION (OFS_TARANIS_PROTOCOLS + sizeof(TR_TARANIS_PROTOCOLS)) + #define OFS_R9MFLEX_FREQ (OFS_R9M_REGION + sizeof(TR_R9M_REGION)) + #define OFS_R9M_FCC_POWER_VALUES (OFS_R9MFLEX_FREQ + sizeof(TR_R9MFLEX_FREQ)) #define OFS_R9M_LBT_POWER_VALUES (OFS_R9M_FCC_POWER_VALUES + sizeof(TR_R9M_FCC_POWER_VALUES)) #define OFS_TELEMETRY_PROTOCOLS (OFS_R9M_LBT_POWER_VALUES + sizeof(TR_R9M_LBT_POWER_VALUES)) #define OFS_XJT_PROTOCOLS (OFS_TELEMETRY_PROTOCOLS + sizeof(TR_TELEMETRY_PROTOCOLS)) @@ -294,7 +295,8 @@ extern const char STR_OPEN9X[]; #define STR_VTRAINERMODES (STR_OPEN9X + OFS_VTRAINERMODES) #define STR_TARANIS_PROTOCOLS (STR_OPEN9X + OFS_TARANIS_PROTOCOLS) - #define STR_R9M_REGION (STR_OPEN9X + OFS_R9M_REGION) + #define STR_R9M_REGION (STR_OPEN9X + OFS_R9M_REGION) + #define STR_R9MFLEX_FREQ (STR_OPEN9X + OFS_R9MFLEX_FREQ) #define STR_R9M_FCC_POWER_VALUES (STR_OPEN9X + OFS_R9M_FCC_POWER_VALUES) #define STR_R9M_LBT_POWER_VALUES (STR_OPEN9X + OFS_R9M_LBT_POWER_VALUES) #define STR_TELEMETRY_PROTOCOLS (STR_OPEN9X + OFS_TELEMETRY_PROTOCOLS) diff --git a/radio/util/fwoptions.py b/radio/util/fwoptions.py index 3e16c3b4f..50b61319e 100755 --- a/radio/util/fwoptions.py +++ b/radio/util/fwoptions.py @@ -79,7 +79,6 @@ options_taranis = { "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"), "multimodule": ("MULTIMODULE", "YES", "NO"), - "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None) } options_taranisplus = { @@ -97,7 +96,6 @@ options_taranisplus = { "shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"), "eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"), "multimodule": ("MULTIMODULE", "YES", "NO"), - "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None) } options_xlite = { @@ -114,7 +112,6 @@ options_xlite = { "eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"), "multimodule": ("MULTIMODULE", "YES", "NO"), "stdr9m": ("MODULE_R9M_FULLSIZE", "YES", None), - "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None) } options_taranisx9e = { @@ -132,7 +129,6 @@ options_taranisx9e = { "eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"), "horussticks": ("STICKS", "HORUS", "STANDARD"), "multimodule": ("MULTIMODULE", "YES", "NO"), - "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None) } options_x12s = { @@ -147,7 +143,6 @@ options_x12s = { "eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"), "multimodule": ("MULTIMODULE", "YES", "NO"), "pcbdev": ("PCBREV", "10", None), - "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None) } options_x10 = { @@ -161,5 +156,4 @@ options_x10 = { "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), "eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"), "multimodule": ("MULTIMODULE", "YES", "NO"), - "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None) }