Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(EdgeTX)

set(VERSION_MAJOR "2")
set(VERSION_MINOR "12")
set(VERSION_REVISION "3")
set(VERSION_REVISION "4")
set(CODENAME "Queen Anne's Revenge")
string(TIMESTAMP BUILD_YEAR "%Y")

Expand Down Expand Up @@ -45,21 +45,34 @@ if(EdgeTX_SUPERBUILD)
else()
set(CACHE_VAR_TYPE :${CACHE_VAR_TYPE})
endif()
list(APPEND CMAKE_ARGS "-D${CACHE_VAR}${CACHE_VAR_TYPE}=${${CACHE_VAR}}")
# Escape CMake's ';' so a multi-path value (CMAKE_PREFIX_PATH) stays one argument
# instead of splitting; LIST_SEPARATOR below restores it.
string(REPLACE ";" "|" CACHE_VAR_VALUE "${${CACHE_VAR}}")
list(APPEND CMAKE_ARGS "-D${CACHE_VAR}${CACHE_VAR_TYPE}=${CACHE_VAR_VALUE}")
endif()
endforeach()
message("-- CMAKE_ARGS: ${CMAKE_ARGS}")
message("-- CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")

# Darwin-Initialize.cmake rewrites CMAKE_OSX_DEPLOYMENT_TARGET's helpstring, so the loop
# above never forwards it - pass it explicitly or sub-builds get the SDK default (#7732).
set(EDGETX_EP_CACHE_ARGS)
if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET)
list(APPEND EDGETX_EP_CACHE_ARGS
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET})
endif()

# Add explicit targets for triggering cmake in the external projects
set_property(DIRECTORY PROPERTY EP_STEP_TARGETS configure clean)

# Native targets
ExternalProject_Add(native
SOURCE_DIR ${CMAKE_SOURCE_DIR}
BINARY_DIR ${CMAKE_BINARY_DIR}/native
LIST_SEPARATOR |
CMAKE_ARGS ${CMAKE_ARGS} -Wno-dev -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
CMAKE_CACHE_ARGS
${EDGETX_EP_CACHE_ARGS}
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_SOURCE_DIR}/cmake/toolchain/native.cmake
-DEdgeTX_SUPERBUILD:BOOL=0
-DNATIVE_BUILD:BOOL=1
Expand All @@ -71,6 +84,7 @@ if(EdgeTX_SUPERBUILD)
ExternalProject_Add(arm-none-eabi
SOURCE_DIR ${CMAKE_SOURCE_DIR}
BINARY_DIR ${CMAKE_BINARY_DIR}/arm-none-eabi
LIST_SEPARATOR |
CMAKE_ARGS ${CMAKE_ARGS} -Wno-dev -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
CMAKE_CACHE_ARGS
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_SOURCE_DIR}/cmake/toolchain/arm-none-eabi.cmake
Expand Down
26 changes: 20 additions & 6 deletions companion/src/firmwares/edgetx/yaml_moduledata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,20 @@ static const YamlLookupTable failsafeLut = {
{ FAILSAFE_RECEIVER, "RECEIVER" },
};

static const YamlLookupTable moduleAntennaModeLut = {
{ GeneralSettings::ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" },
{ GeneralSettings::ANTENNA_MODE_ASK, "MODE_ASK" },
{ GeneralSettings::ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" },
{ GeneralSettings::ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" },
};

// Firmware built before the field was made unconditional emitted antennaMode on
// boards without an external antenna, where it aliased the top bits of subType.
static bool hasModuleAntennaMode()
{
return Boards::getCapability(getCurrentBoard(), Board::HasExternalAntenna);
}

static int exportPpmDelay(int delay) { return (delay - 300) / 50; }
static int importPpmDelay(int delay) { return 300 + 50 * delay; }

Expand Down Expand Up @@ -197,8 +211,8 @@ Node convert<ModuleData>::encode(const ModuleData& rhs)
node["channelsStart"] = rhs.channelsStart;
node["channelsCount"] = rhs.channelsCount;
node["failsafeMode"] = LookupValue(failsafeLut, rhs.failsafeMode);
if (rhs.antennaMode)
node["antennaMode"] = rhs.antennaMode;
if (rhs.antennaMode && hasModuleAntennaMode())
node["antennaMode"] = LookupValue(moduleAntennaModeLut, rhs.antennaMode);

Node mod;
switch (protocol) {
Expand Down Expand Up @@ -363,8 +377,8 @@ bool convert<ModuleData>::decode(const Node& node, ModuleData& rhs)
node["channelsStart"] >> rhs.channelsStart;
node["channelsCount"] >> rhs.channelsCount;
node["failsafeMode"] >> failsafeLut >> rhs.failsafeMode;
if (node["antennaMode"])
node["antennaMode"] >> rhs.antennaMode;
if (node["antennaMode"] && hasModuleAntennaMode())
node["antennaMode"] >> moduleAntennaModeLut >> rhs.antennaMode;

if (node["mod"]) {
const Node& mod = node["mod"];
Expand All @@ -389,8 +403,8 @@ bool convert<ModuleData>::decode(const Node& node, ModuleData& rhs)
pxx["power"] >> rhs.pxx.power;
// pxx["receiverTelemetryOff"] >> rhs.pxx.receiverTelemetryOff;
// pxx["receiverHigherChannels"] >> rhs.pxx.receiverHigherChannels;
// Migration: read old pxx.antennaMode into top-level antennaMode
if (pxx["antennaMode"]) {
// Migration: legacy raw-int antennaMode, only if not already set
if (!node["antennaMode"] && pxx["antennaMode"] && hasModuleAntennaMode()) {
pxx["antennaMode"] >> rhs.antennaMode;
}
} else if (mod["sbus"]) {
Expand Down
3 changes: 1 addition & 2 deletions companion/src/modeledit/customfunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model,
functions(model ? model->customFn : generalSettings.customFn),
mediaPlayerCurrent(-1),
mediaPlayer(nullptr),
audioOutput(new QAudioOutput()),
modelsUpdateCnt(0)
{
lock = true;
Expand Down Expand Up @@ -290,7 +289,7 @@ bool CustomFunctionsPanel::playSound(int index)
stopSound(mediaPlayerCurrent);

mediaPlayer = new QMediaPlayer(this);
mediaPlayer->setAudioOutput(audioOutput);
mediaPlayer->setAudioOutput(new QAudioOutput(mediaPlayer));

if (functions[index].func == FuncPlaySound)
mediaPlayer->setSource(QUrl(path.prepend("qrc")));
Expand Down
1 change: 0 additions & 1 deletion companion/src/modeledit/customfunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ class CustomFunctionsPanel : public GenericPanel
QComboBox * fswtchRepeat[CPN_MAX_SPECIAL_FUNCTIONS];
QComboBox * fswtchGVmode[CPN_MAX_SPECIAL_FUNCTIONS];
QMediaPlayer * mediaPlayer;
QAudioOutput * audioOutput;

int selectedIndex;
int fswCapability;
Expand Down
2 changes: 2 additions & 0 deletions companion/targets/mac/MacOSXBundleInfo.plist.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
<true/>

<!-- added since cmake/qt do not add these by default -->
<key>LSMinimumSystemVersion</key>
<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
Expand Down
37 changes: 36 additions & 1 deletion companion/targets/mac/bundle_verify.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ endif()
file(GLOB_RECURSE _candidates "${_app}/Contents/*")

set(_offenders "")
set(_toonew "")
set(_checked 0)
set(_max_minos "0.0")
set(_target_minos "@CMAKE_OSX_DEPLOYMENT_TARGET@")
foreach(_file IN LISTS _candidates)
if(IS_SYMLINK "${_file}" OR IS_DIRECTORY "${_file}")
continue()
Expand All @@ -45,6 +48,25 @@ foreach(_file IN LISTS _candidates)
endif()
math(EXPR _checked "${_checked} + 1")

# macOS refuses to launch an app stamped above the running system - that is how 2.12.3
# became "requires macOS 15.0 or later" (issue #7732).
execute_process(
COMMAND otool -l "${_file}"
OUTPUT_VARIABLE _otool_l_out
ERROR_QUIET
RESULT_VARIABLE _otool_l_res
)
if(_otool_l_res EQUAL 0 AND _otool_l_out MATCHES "minos ([0-9]+(\.[0-9]+)+)")
set(_minos "${CMAKE_MATCH_1}")
if(_minos VERSION_GREATER _max_minos)
set(_max_minos "${_minos}")
endif()
if(_target_minos AND _minos VERSION_GREATER _target_minos)
file(RELATIVE_PATH _rel "${_app}" "${_file}")
list(APPEND _toonew "${_rel}: minos ${_minos}")
endif()
endif()

string(REPLACE "\n" ";" _lines "${_otool_out}")
foreach(_line IN LISTS _lines)
string(REGEX MATCH "^\t([^ ]+)" _matched "${_line}")
Expand Down Expand Up @@ -77,7 +99,20 @@ if(_offenders)
"Re-run with -DCOMPANION_VERIFY_BUNDLE=OFF to package anyway.")
endif()

message(STATUS "Bundle verification: ${_checked} Mach-O files, no external references")
if(_toonew)
list(REMOVE_DUPLICATES _toonew)
string(REPLACE ";" "\n " _report "${_toonew}")
message(FATAL_ERROR
"Bundle contains Mach-O files built for a newer macOS than the deployment target "
"(${_target_minos}) - macOS refuses to launch an app stamped above the running "
"system:\n ${_report}\n"
"Re-run with -DCOMPANION_VERIFY_BUNDLE=OFF to package anyway.")
endif()

# CPack discards message(STATUS) from install scripts, so echo via a subprocess - otherwise
# the bundle's real macOS floor never reaches the packaging log.
execute_process(COMMAND ${CMAKE_COMMAND} -E echo
"-- Bundle verification: ${_checked} Mach-O files, no external references, minimum macOS ${_max_minos}")

# The bundle seal is a separate concern from the per-Mach-O signatures: dyld does not consult
# CodeResources when loading, so a stale seal does not stop the app launching. It would matter
Expand Down
5 changes: 5 additions & 0 deletions radio/src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,11 @@ int cliDisplay(const char ** argv)
gettime(&utm);
cliSerialPrint("rtc = %4d-%02d-%02d %02d:%02d:%02d.%02d0", utm.tm_year+TM_YEAR_BASE, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100);
}
#if defined(VOLUME_I2C_ADDRESS)
else if (!strcmp(argv[1], "volume")) {
cliSerialPrint("volume = %d", getVolume());
}
#endif
else if (!strcmp(argv[1], "uid")) {
char str[LEN_CPU_UID+1];
getCPUUniqueID(str);
Expand Down
10 changes: 4 additions & 6 deletions radio/src/datastructs_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,17 +499,15 @@ PACK(struct PpmModule {
});

PACK(struct ModuleData {
uint8_t type ENUM(ModuleType) CUST(r_moduleType, w_moduleType);
// antennaMode stays unconditional as boards differing on EXTERNAL_ANTENNA share
// generated YAML descriptors.
uint8_t type:6 ENUM(ModuleType) CUST(r_moduleType, w_moduleType);
int8_t antennaMode:2 ENUM(AntennaModes);
CUST_ATTR(subType,r_modSubtype,w_modSubtype);
uint8_t channelsStart;
int8_t channelsCount CUST(r_channelsCount,w_channelsCount); // 0=8 channels
uint8_t failsafeMode:4 ENUM(FailsafeModes); // only 3 bits used
#if defined(EXTERNAL_ANTENNA)
uint8_t subType:2 SKIP;
int8_t antennaMode:2 ENUM(AntennaModes);
#else
uint8_t subType:4 SKIP;
#endif

union {
uint8_t raw[PXX2_MAX_RECEIVERS_PER_MODULE * PXX2_LEN_RX_NAME + 1];
Expand Down
4 changes: 3 additions & 1 deletion radio/src/gui/128x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2452,8 +2452,10 @@ void menuModelSetup(event_t event)
#if defined(AFHDS3) && defined(HARDWARE_EXTERNAL_MODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS:
#endif
#if (defined(MULTIMODULE) | defined(DSMP) | defined(AFHDS3)) && defined(HARDWARE_EXTERNAL_MODULE)
#if defined(DSMP) && defined(HARDWARE_EXTERNAL_MODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DSMP_STATUS:
#endif
#if defined(MULTIMODULE) || defined(AFHDS3) || defined(DSMP)
{
// MultiModule & LemonDSMP & AFHDS3 Status
lcdDrawTextIndented(y, STR_MODULE_STATUS);
Expand Down
41 changes: 27 additions & 14 deletions radio/src/pulses/crossfire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,20 @@ uint8_t createCrossfireModelIDFrame(uint8_t moduleIdx, uint8_t * frame)
uint8_t createCrossfireChannelsFrame(uint8_t moduleIdx, uint8_t * frame, int16_t * pulses)
{
//
// sends channel data and also communicates commanded armed status in arming mode Switch.
// frame len 24 -> arming mode CH5: module will use channel 5
// frame len 25 -> arming mode Switch: send commanded armed status in extra byte after channel data
//
ModuleData *md = &g_model.moduleData[moduleIdx];

uint8_t armingMode = md->crsf.crsfArmingMode; // 0 = Channel mode, 1 = Switch mode
uint8_t lenAdjust = (armingMode == ARMING_MODE_SWITCH) ? 1 : 0;

// sends channel data and also communicates status information in status byte:
// - arming status in Switch mode (bit 0)
// - arming mode Switch or CH5 (bit 1)
// - bits 2-7 spare
//
uint8_t * buf = frame;
*buf++ = MODULE_ADDRESS;
*buf++ = 24 + lenAdjust; // 1(ID) + 22(channel data) + (+1 extra byte if Switch mode) + 1(CRC)
*buf++ = 25; // 1(ID) + 22(channel data) + 1(extra status byte) + 1(CRC)
uint8_t * crc_start = buf;
*buf++ = CHANNELS_ID;

//
// assemble channel data
//
uint32_t bits = 0;
uint8_t bitsavailable = 0;
for (int i=0; i<CROSSFIRE_CHANNELS_COUNT; i++) {
Expand All @@ -122,14 +122,27 @@ uint8_t createCrossfireChannelsFrame(uint8_t moduleIdx, uint8_t * frame, int16_t
bitsavailable -= 8;
}
}

if (armingMode == ARMING_MODE_SWITCH) {

//
// assemble status byte
//
ModuleData *md = &g_model.moduleData[moduleIdx];

if (md->crsf.crsfArmingMode == ARMING_MODE_SWITCH) {
swsrc_t sw = md->crsf.crsfArmingTrigger;

*buf++ = (sw != SWSRC_NONE) && getSwitch(sw, 0); // commanded armed status in Switch mode
*buf = (sw != SWSRC_NONE) && getSwitch(sw, 0); // commanded armed status in Switch mode
} else {
*buf = 0x02; // flag arming mode CH5
}

buf++;

*buf++ = crc8(crc_start, 23 + lenAdjust);
//
// add crc
//
*buf++ = crc8(crc_start, 24);

return buf - frame;
}

Expand Down
14 changes: 7 additions & 7 deletions radio/src/pulses/pulses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ void pulsesRestartModuleUnsafe(uint8_t module)
{
if (module >= MAX_MODULES)
return;

auto mod_drv = pulsesGetModuleDriver(module);
if (!mod_drv->drv) return;

auto drv = mod_drv->drv;
drv->deinit(mod_drv->ctx);
mod_drv->ctx = drv->init(module);
Expand Down Expand Up @@ -351,7 +351,7 @@ uint8_t getRequiredProtocol(uint8_t module)
case MODULE_TYPE_LEMON_DSMP:
protocol = PROTOCOL_CHANNELS_DSMP;
break;

default:
protocol = PROTOCOL_CHANNELS_NONE;
break;
Expand Down Expand Up @@ -390,7 +390,7 @@ static void _init_module(uint8_t module, const etx_proto_driver_t* drv)
// board specific hook
if (_on_module_init)
_on_module_init(module, drv);

// power ON
modulePortSetPower(module, true);
TRACE("Module #%d init succeeded", module);
Expand All @@ -408,7 +408,7 @@ static void _deinit_module(uint8_t module)
auto drv = mod->drv;
if (_on_module_deinit)
_on_module_deinit(module, drv);

// de-init
auto ctx = mod->ctx;
drv->deinit(ctx);
Expand Down Expand Up @@ -486,7 +486,7 @@ static void pulsesEnableModule(uint8_t module, uint8_t protocol)
break;
#endif

#if defined(DSM2)
#if defined(DSMP)
case PROTOCOL_CHANNELS_DSMP:
_init_module(module, &DSMPDriver);
break;
Expand Down Expand Up @@ -548,7 +548,7 @@ void pulsesSendNextFrame(uint8_t module)

if (_handle_async_restart(module))
return;

pulsesEnableModule(module, protocol);
moduleState[module].protocol = protocol;
return;
Expand Down
3 changes: 2 additions & 1 deletion radio/src/storage/yaml/yaml_datastructs_128x64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,8 @@ static const struct YamlNode union_anonymous_4_elmts[] = {
};
static const struct YamlNode struct_ModuleData[] = {
YAML_IDX,
YAML_UNSIGNED_CUST( "type", 8, r_moduleType, w_moduleType ),
YAML_UNSIGNED_CUST( "type", 6, r_moduleType, w_moduleType ),
YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL),
YAML_CUSTOM("subType",r_modSubtype,w_modSubtype),
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
Expand Down
3 changes: 2 additions & 1 deletion radio/src/storage/yaml/yaml_datastructs_c14.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@ static const struct YamlNode union_anonymous_4_elmts[] = {
};
static const struct YamlNode struct_ModuleData[] = {
YAML_IDX,
YAML_UNSIGNED_CUST( "type", 8, r_moduleType, w_moduleType ),
YAML_UNSIGNED_CUST( "type", 6, r_moduleType, w_moduleType ),
YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL),
YAML_CUSTOM("subType",r_modSubtype,w_modSubtype),
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
Expand Down
3 changes: 2 additions & 1 deletion radio/src/storage/yaml/yaml_datastructs_f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,8 @@ static const struct YamlNode union_anonymous_4_elmts[] = {
};
static const struct YamlNode struct_ModuleData[] = {
YAML_IDX,
YAML_UNSIGNED_CUST( "type", 8, r_moduleType, w_moduleType ),
YAML_UNSIGNED_CUST( "type", 6, r_moduleType, w_moduleType ),
YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL),
YAML_CUSTOM("subType",r_modSubtype,w_modSubtype),
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
Expand Down
Loading