mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-20 23:05:17 +03:00
Merge remote-tracking branch 'origin/development' into dzikuvx-mr-cruise-experiments
This commit is contained in:
commit
8132e59b7e
44 changed files with 458 additions and 361 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -20,6 +20,4 @@ docs/Manual.pdf
|
|||
README.pdf
|
||||
|
||||
# build generated files
|
||||
/src/main/fc/settings_generated.h
|
||||
/src/main/fc/settings_generated.c
|
||||
/settings.json
|
||||
|
|
35
Makefile
35
Makefile
|
@ -274,9 +274,10 @@ TARGET_BIN = $(BIN_DIR)/$(FORKNAME)_$(FC_VER)_$(TARGET)_$(BUILD_SUFFIX).bin
|
|||
TARGET_HEX = $(BIN_DIR)/$(FORKNAME)_$(FC_VER)_$(TARGET)_$(BUILD_SUFFIX).hex
|
||||
endif
|
||||
|
||||
TARGET_OBJ_DIR = $(OBJECT_DIR)/$(TARGET)
|
||||
TARGET_ELF = $(OBJECT_DIR)/$(FORKNAME)_$(TARGET).elf
|
||||
TARGET_OBJS = $(addsuffix .o,$(addprefix $(OBJECT_DIR)/$(TARGET)/,$(basename $(TARGET_SRC))))
|
||||
TARGET_DEPS = $(addsuffix .d,$(addprefix $(OBJECT_DIR)/$(TARGET)/,$(basename $(TARGET_SRC))))
|
||||
TARGET_OBJS = $(addsuffix .o,$(addprefix $(TARGET_OBJ_DIR)/,$(basename $(TARGET_SRC))))
|
||||
TARGET_DEPS = $(addsuffix .d,$(addprefix $(TARGET_OBJ_DIR)/,$(basename $(TARGET_SRC))))
|
||||
TARGET_MAP = $(OBJECT_DIR)/$(FORKNAME)_$(TARGET).map
|
||||
|
||||
|
||||
|
@ -285,20 +286,23 @@ CLEAN_ARTIFACTS += $(TARGET_HEX)
|
|||
CLEAN_ARTIFACTS += $(TARGET_ELF) $(TARGET_OBJS) $(TARGET_MAP)
|
||||
|
||||
# Make sure build date and revision is updated on every incremental build
|
||||
$(OBJECT_DIR)/$(TARGET)/build/version.o : $(TARGET_SRC)
|
||||
$(TARGET_OBJ_DIR)/build/version.o : $(TARGET_SRC)
|
||||
|
||||
# Settings generator
|
||||
.PHONY: .FORCE settings clean-settings
|
||||
UTILS_DIR = $(ROOT)/src/utils
|
||||
SETTINGS_GENERATOR = $(UTILS_DIR)/settings.rb
|
||||
BUILD_STAMP = $(UTILS_DIR)/build_stamp.rb
|
||||
STAMP = $(BIN_DIR)/build.stamp
|
||||
UTILS_DIR = $(ROOT)/src/utils
|
||||
SETTINGS_GENERATOR = $(UTILS_DIR)/settings.rb
|
||||
BUILD_STAMP = $(UTILS_DIR)/build_stamp.rb
|
||||
STAMP = $(TARGET_OBJ_DIR)/build.stamp
|
||||
|
||||
GENERATED_SETTINGS = $(SRC_DIR)/fc/settings_generated.h $(SRC_DIR)/fc/settings_generated.c
|
||||
SETTINGS_FILE = $(SRC_DIR)/fc/settings.yaml
|
||||
GENERATED_FILES = $(GENERATED_SETTINGS)
|
||||
GENERATED_SETTINGS = $(TARGET_OBJ_DIR)/settings_generated.h $(TARGET_OBJ_DIR)/settings_generated.c
|
||||
SETTINGS_FILE = $(SRC_DIR)/fc/settings.yaml
|
||||
GENERATED_FILES = $(GENERATED_SETTINGS)
|
||||
$(GENERATED_SETTINGS): $(SETTINGS_GENERATOR) $(SETTINGS_FILE) $(STAMP)
|
||||
|
||||
# Make sure the generated files are in the include path
|
||||
CFLAGS += -I$(TARGET_OBJ_DIR)
|
||||
|
||||
$(STAMP): .FORCE
|
||||
$(V1) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(BUILD_STAMP) $(SETTINGS_FILE) $(STAMP)
|
||||
|
||||
|
@ -306,7 +310,7 @@ $(STAMP): .FORCE
|
|||
# See https://www.gnu.org/software/make/manual/make.html#Pattern-Examples
|
||||
%generated.h %generated.c:
|
||||
$(V1) echo "settings.yaml -> settings_generated.h, settings_generated.c" "$(STDOUT)"
|
||||
$(V1) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(SETTINGS_GENERATOR) . $(SETTINGS_FILE)
|
||||
$(V1) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(SETTINGS_GENERATOR) . $(SETTINGS_FILE) -o $(TARGET_OBJ_DIR)
|
||||
|
||||
settings-json:
|
||||
$(V0) CFLAGS="$(CFLAGS)" TARGET=$(TARGET) ruby $(SETTINGS_GENERATOR) . $(SETTINGS_FILE) --json settings.json
|
||||
|
@ -329,18 +333,18 @@ $(TARGET_ELF): $(TARGET_OBJS)
|
|||
$(V0) $(SIZE) $(TARGET_ELF)
|
||||
|
||||
# Compile
|
||||
$(OBJECT_DIR)/$(TARGET)/%.o: %.c
|
||||
$(TARGET_OBJ_DIR)/%.o: %.c
|
||||
$(V1) mkdir -p $(dir $@)
|
||||
$(V1) echo %% $(notdir $<) "$(STDOUT)"
|
||||
$(V1) $(CROSS_CC) -c -o $@ $(CFLAGS) $<
|
||||
|
||||
# Assemble
|
||||
$(OBJECT_DIR)/$(TARGET)/%.o: %.s
|
||||
$(TARGET_OBJ_DIR)/%.o: %.s
|
||||
$(V1) mkdir -p $(dir $@)
|
||||
$(V1) echo %% $(notdir $<) "$(STDOUT)"
|
||||
$(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
|
||||
|
||||
$(OBJECT_DIR)/$(TARGET)/%.o: %.S
|
||||
$(TARGET_OBJ_DIR)/%.o: %.S
|
||||
$(V1) mkdir -p $(dir $@)
|
||||
$(V1) echo %% $(notdir $<) "$(STDOUT)"
|
||||
$(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
|
||||
|
@ -377,8 +381,7 @@ $(VALID_TARGETS):
|
|||
clean:
|
||||
$(V0) echo "Cleaning $(TARGET)"
|
||||
$(V0) rm -f $(CLEAN_ARTIFACTS)
|
||||
$(V0) rm -rf $(OBJECT_DIR)/$(TARGET)
|
||||
$(V0) rm -f $(GENERATED_SETTINGS)
|
||||
$(V0) rm -rf $(TARGET_OBJ_DIR)
|
||||
$(V0) echo "Cleaning $(TARGET) succeeded."
|
||||
|
||||
## clean_test : clean up all temporary / machine-generated files (tests)
|
||||
|
|
|
@ -8,8 +8,7 @@ Current support of rangefinders in INAV is very limited. They are used only to:
|
|||
|
||||
* landing detection for multirotors
|
||||
* automated landing support for fixed wings
|
||||
|
||||
INAV currently does not support _terrain following_ or _rangefinder supported altitude hold_ flight modes.
|
||||
* _Experimental_ terrain following (Surface) flight mode activated with _SURFACE_ and _ALTHOLD_ flight mode
|
||||
|
||||
## Hardware
|
||||
|
||||
|
@ -18,15 +17,16 @@ Following rangefinders are supported:
|
|||
* HC-SR04 - ***DO NOT USE*** HC-SR04 while most popular is not suited to use in noise reach environments (like multirotors). It is proven that this sonar rangefinder start to report random values already at 1.5m above solid concrete surface. Reported altitude is valid up to only 75cm above concrete. ***DO NOT USE***
|
||||
* US-100 in trigger-echo mode - Can be used as direct replacement of _HC-SR04_ when `rangefinder_hardware` is set to _HCSR04_. Useful up to 2m over concrete and correctly reporting _out of range_ when out of range
|
||||
* SRF10 - experimental
|
||||
* HCSR04I2C - is a simple [DIY rangefinder interface](https://github.com/iNavFlight/INAV-Rangefinder-I2C-interface). Can be used to connect when flight controller has no Trigger-Echo ports.
|
||||
* INAV_I2C - is a simple [DIY rangefinder interface with Arduino Pro Mini 3.3V](https://github.com/iNavFlight/inav-rangefinder). Can be used to connect when flight controller has no Trigger-Echo ports.
|
||||
* VL53L0X - simple laser rangefinder usable up to 75cm
|
||||
* UIB - experimental
|
||||
* MSP - experimental
|
||||
|
||||
## Connections
|
||||
|
||||
Target dependent in case of Trigger/Echo solutions like HC-SR04 and US-100.
|
||||
I2C solutions like VL53L0X or HCSR04I2C can be connected to I2C port and used as any other I2C device.
|
||||
Target dependent in case of Trigger/Echo solutions like `HC-SR04` and `US-100`.
|
||||
I2C solutions like `VL53L0X` or `INAV_I2C` can be connected to I2C port and used as any other I2C device.
|
||||
|
||||
#### Constraints
|
||||
|
||||
Target dependent in case of Trigger/Echo solutions like HC-SR04 and US-100. No constrains for I2C like VL53L0X or HCSR04I2C.
|
||||
Target dependent in case of Trigger/Echo solutions like `HC-SR04` and `US-100`. No constrains for I2C like `VL53L0X` or `INAV_I2C`.
|
|
@ -59,6 +59,7 @@ typedef enum {
|
|||
DEBUG_ALWAYS,
|
||||
DEBUG_STAGE2,
|
||||
DEBUG_WIND_ESTIMATOR,
|
||||
DEBUG_SAG_COMP_VOLTAGE,
|
||||
DEBUG_COUNT
|
||||
} debugType_e;
|
||||
|
||||
|
@ -75,4 +76,4 @@ void debugTracePrintBufferHex(bool synchronous, const void *buffer, size_t size)
|
|||
#define DEBUG_TRACE_SYNC(fmt, ...)
|
||||
#define DEBUG_TRACE_BUFFER_HEX(buf, size)
|
||||
#define DEBUG_TRACE_BUFFER_HEX_SYNC(buf, size)
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -775,8 +775,13 @@ long cmsMenuExit(displayPort_t *pDisplay, const void *ptr)
|
|||
|
||||
void cmsYieldDisplay(displayPort_t *pPort, timeMs_t duration)
|
||||
{
|
||||
// Check if we're already yielding, in that case just extend
|
||||
// the yield time without releasing the display again, otherwise
|
||||
// the yield/grab become unbalanced.
|
||||
if (cmsYieldUntil == 0) {
|
||||
displayRelease(pPort);
|
||||
}
|
||||
cmsYieldUntil = millis() + duration;
|
||||
displayRelease(pPort);
|
||||
}
|
||||
|
||||
// Stick/key detection and key codes
|
||||
|
@ -1209,6 +1214,8 @@ void cmsUpdate(uint32_t currentTimeUs)
|
|||
|
||||
// Only scan keys and draw if we're not yielding
|
||||
if (cmsYieldUntil == 0) {
|
||||
// XXX: Note that one call to cmsScanKeys() might generate multiple keypresses
|
||||
// when repeating, that's why cmsYieldDisplay() has to check for multiple calls.
|
||||
rcDelayMs = cmsScanKeys(currentTimeMs, lastCalledMs, rcDelayMs);
|
||||
// Check again, the keypress might have produced a yield
|
||||
if (cmsYieldUntil == 0) {
|
||||
|
|
|
@ -148,6 +148,7 @@ static const OSD_Entry menuOsdElemsEntries[] =
|
|||
|
||||
OSD_ELEMENT_ENTRY("RSSI", OSD_RSSI_VALUE),
|
||||
OSD_ELEMENT_ENTRY("MAIN BATTERY", OSD_MAIN_BATT_VOLTAGE),
|
||||
OSD_ELEMENT_ENTRY("MAIN BATT SC", OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE),
|
||||
OSD_ELEMENT_ENTRY("CELL VOLTAGE", OSD_MAIN_BATT_CELL_VOLTAGE),
|
||||
OSD_ELEMENT_ENTRY("CROSSHAIRS", OSD_CROSSHAIRS),
|
||||
OSD_ELEMENT_ENTRY("HORIZON", OSD_ARTIFICIAL_HORIZON),
|
||||
|
|
|
@ -141,7 +141,7 @@ int16_t getAxisRcCommand(int16_t rawData, int16_t rate, int16_t deadband)
|
|||
{
|
||||
int16_t stickDeflection;
|
||||
|
||||
stickDeflection = constrain(rawData - rxConfig()->midrc, -500, 500);
|
||||
stickDeflection = constrain(rawData - PWM_RANGE_MIDDLE, -500, 500);
|
||||
stickDeflection = applyDeadband(stickDeflection, deadband);
|
||||
|
||||
return rcLookup(stickDeflection, rate);
|
||||
|
@ -401,14 +401,6 @@ void tryArm(void)
|
|||
#endif
|
||||
statsOnArm();
|
||||
|
||||
#ifdef USE_RANGEFINDER
|
||||
/*
|
||||
* Since each arm can happen over different surface type, we have to reset
|
||||
* previously computed max. dynamic range threshold
|
||||
*/
|
||||
rangefinderResetDynamicThreshold();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -488,7 +480,7 @@ void processRx(timeUs_t currentTimeUs)
|
|||
|
||||
updateActivatedModes();
|
||||
|
||||
if (!cliMode) {
|
||||
if ((!cliMode) && (!FLIGHT_MODE(FAILSAFE_MODE))) {
|
||||
updateAdjustmentStates();
|
||||
processRcAdjustments(CONST_CAST(controlRateConfig_t*, currentControlRateProfile));
|
||||
}
|
||||
|
|
|
@ -647,7 +647,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
|
|||
break;
|
||||
|
||||
case MSP_MISC:
|
||||
sbufWriteU16(dst, rxConfig()->midrc);
|
||||
sbufWriteU16(dst, PWM_RANGE_MIDDLE);
|
||||
|
||||
sbufWriteU16(dst, motorConfig()->minthrottle);
|
||||
sbufWriteU16(dst, motorConfig()->maxthrottle);
|
||||
|
@ -677,7 +677,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
|
|||
break;
|
||||
|
||||
case MSP2_INAV_MISC:
|
||||
sbufWriteU16(dst, rxConfig()->midrc);
|
||||
sbufWriteU16(dst, PWM_RANGE_MIDDLE);
|
||||
|
||||
sbufWriteU16(dst, motorConfig()->minthrottle);
|
||||
sbufWriteU16(dst, motorConfig()->maxthrottle);
|
||||
|
@ -829,7 +829,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
|
|||
case MSP_RX_CONFIG:
|
||||
sbufWriteU8(dst, rxConfig()->serialrx_provider);
|
||||
sbufWriteU16(dst, rxConfig()->maxcheck);
|
||||
sbufWriteU16(dst, rxConfig()->midrc);
|
||||
sbufWriteU16(dst, PWM_RANGE_MIDDLE);
|
||||
sbufWriteU16(dst, rxConfig()->mincheck);
|
||||
sbufWriteU8(dst, rxConfig()->spektrum_sat_bind);
|
||||
sbufWriteU16(dst, rxConfig()->rx_min_usec);
|
||||
|
@ -1595,7 +1595,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
|
|||
|
||||
case MSP_SET_MISC:
|
||||
if (dataSize >= 22) {
|
||||
rxConfigMutable()->midrc = constrain(sbufReadU16(src), MIDRC_MIN, MIDRC_MAX);
|
||||
sbufReadU16(src); // midrc
|
||||
|
||||
motorConfigMutable()->minthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
|
||||
motorConfigMutable()->maxthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
|
||||
|
@ -1635,7 +1635,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
|
|||
|
||||
case MSP2_INAV_SET_MISC:
|
||||
if (dataSize == 39) {
|
||||
rxConfigMutable()->midrc = constrain(sbufReadU16(src), MIDRC_MIN, MIDRC_MAX);
|
||||
sbufReadU16(src); // midrc
|
||||
|
||||
motorConfigMutable()->minthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
|
||||
motorConfigMutable()->maxthrottle = constrain(sbufReadU16(src), PWM_RANGE_MIN, PWM_RANGE_MAX);
|
||||
|
@ -2264,7 +2264,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
|
|||
if (dataSize >= 24) {
|
||||
rxConfigMutable()->serialrx_provider = sbufReadU8(src);
|
||||
rxConfigMutable()->maxcheck = sbufReadU16(src);
|
||||
rxConfigMutable()->midrc = sbufReadU16(src);
|
||||
sbufReadU16(src); // midrc
|
||||
rxConfigMutable()->mincheck = sbufReadU16(src);
|
||||
rxConfigMutable()->spektrum_sat_bind = sbufReadU8(src);
|
||||
rxConfigMutable()->rx_min_usec = sbufReadU16(src);
|
||||
|
|
|
@ -58,6 +58,7 @@ static const box_t boxes[CHECKBOX_ITEM_COUNT + 1] = {
|
|||
{ BOXBEEPERON, "BEEPER", 13 },
|
||||
{ BOXLEDLOW, "LEDLOW", 15 },
|
||||
{ BOXLIGHTS, "LIGHTS", 16 },
|
||||
{ BOXOSD, "OSD SW", 19 },
|
||||
{ BOXTELEMETRY, "TELEMETRY", 20 },
|
||||
{ BOXAUTOTUNE, "AUTO TUNE", 21 },
|
||||
{ BOXBLACKBOX, "BLACKBOX", 26 },
|
||||
|
@ -228,6 +229,8 @@ void initActiveBoxIds(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
activeBoxIds[activeBoxIdCount++] = BOXOSD;
|
||||
|
||||
#ifdef USE_TELEMETRY
|
||||
if (feature(FEATURE_TELEMETRY) && telemetryConfig()->telemetry_switch)
|
||||
activeBoxIds[activeBoxIdCount++] = BOXTELEMETRY;
|
||||
|
@ -282,6 +285,7 @@ void packBoxModeFlags(boxBitmask_t * mspBoxModeFlags)
|
|||
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBEEPERON)), BOXBEEPERON);
|
||||
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXLEDLOW)), BOXLEDLOW);
|
||||
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXLIGHTS)), BOXLIGHTS);
|
||||
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXOSD)), BOXOSD);
|
||||
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXTELEMETRY)), BOXTELEMETRY);
|
||||
CHECK_ACTIVE_BOX(IS_ENABLED(ARMING_FLAG(ARMED)), BOXARM);
|
||||
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBLACKBOX)), BOXBLACKBOX);
|
||||
|
|
|
@ -106,8 +106,10 @@ void taskUpdateBattery(timeUs_t currentTimeUs)
|
|||
#ifdef USE_ADC
|
||||
if (feature(FEATURE_VBAT))
|
||||
batteryUpdate(BatMonitoringTimeSinceLastServiced);
|
||||
if (feature(FEATURE_VBAT) && feature(FEATURE_CURRENT_METER))
|
||||
if (feature(FEATURE_VBAT) && feature(FEATURE_CURRENT_METER)) {
|
||||
powerMeterUpdate(BatMonitoringTimeSinceLastServiced);
|
||||
sagCompensatedVBatUpdate(currentTimeUs);
|
||||
}
|
||||
#endif
|
||||
batMonitoringLastServiced = currentTimeUs;
|
||||
}
|
||||
|
|
|
@ -475,9 +475,9 @@ void processRcAdjustments(controlRateConfig_t *controlRateConfig)
|
|||
|
||||
if (adjustmentState->config->mode == ADJUSTMENT_MODE_STEP) {
|
||||
int delta;
|
||||
if (rcData[channelIndex] > rxConfig()->midrc + 200) {
|
||||
if (rcData[channelIndex] > PWM_RANGE_MIDDLE + 200) {
|
||||
delta = adjustmentState->config->data.stepConfig.step;
|
||||
} else if (rcData[channelIndex] < rxConfig()->midrc - 200) {
|
||||
} else if (rcData[channelIndex] < PWM_RANGE_MIDDLE - 200) {
|
||||
delta = 0 - adjustmentState->config->data.stepConfig.step;
|
||||
} else {
|
||||
// returning the switch to the middle immediately resets the ready state
|
||||
|
|
|
@ -101,7 +101,7 @@ bool areSticksDeflectedMoreThanPosHoldDeadband(void)
|
|||
throttleStatus_e calculateThrottleStatus(void)
|
||||
{
|
||||
const uint16_t deadband3d_throttle = rcControlsConfig()->deadband3d_throttle;
|
||||
if (feature(FEATURE_3D) && (rcData[THROTTLE] > (rxConfig()->midrc - deadband3d_throttle) && rcData[THROTTLE] < (rxConfig()->midrc + deadband3d_throttle)))
|
||||
if (feature(FEATURE_3D) && (rcData[THROTTLE] > (PWM_RANGE_MIDDLE - deadband3d_throttle) && rcData[THROTTLE] < (PWM_RANGE_MIDDLE + deadband3d_throttle)))
|
||||
return THROTTLE_LOW;
|
||||
else if (!feature(FEATURE_3D) && (rcData[THROTTLE] < rxConfig()->mincheck))
|
||||
return THROTTLE_LOW;
|
||||
|
@ -111,8 +111,8 @@ throttleStatus_e calculateThrottleStatus(void)
|
|||
|
||||
rollPitchStatus_e calculateRollPitchCenterStatus(void)
|
||||
{
|
||||
if (((rcData[PITCH] < (rxConfig()->midrc + AIRMODE_DEADBAND)) && (rcData[PITCH] > (rxConfig()->midrc -AIRMODE_DEADBAND)))
|
||||
&& ((rcData[ROLL] < (rxConfig()->midrc + AIRMODE_DEADBAND)) && (rcData[ROLL] > (rxConfig()->midrc -AIRMODE_DEADBAND))))
|
||||
if (((rcData[PITCH] < (PWM_RANGE_MIDDLE + AIRMODE_DEADBAND)) && (rcData[PITCH] > (PWM_RANGE_MIDDLE -AIRMODE_DEADBAND)))
|
||||
&& ((rcData[ROLL] < (PWM_RANGE_MIDDLE + AIRMODE_DEADBAND)) && (rcData[ROLL] > (PWM_RANGE_MIDDLE -AIRMODE_DEADBAND))))
|
||||
return CENTERED;
|
||||
|
||||
return NOT_CENTERED;
|
||||
|
@ -328,7 +328,7 @@ void processRcStickPositions(throttleStatus_e throttleStatus)
|
|||
}
|
||||
}
|
||||
|
||||
int32_t getRcStickDeflection(int32_t axis, uint16_t midrc) {
|
||||
return MIN(ABS(rcData[axis] - midrc), 500);
|
||||
int32_t getRcStickDeflection(int32_t axis) {
|
||||
return MIN(ABS(rcData[axis] - PWM_RANGE_MIDDLE), 500);
|
||||
}
|
||||
|
||||
|
|
|
@ -99,4 +99,4 @@ throttleStatus_e calculateThrottleStatus(void);
|
|||
rollPitchStatus_e calculateRollPitchCenterStatus(void);
|
||||
void processRcStickPositions(throttleStatus_e throttleStatus);
|
||||
|
||||
int32_t getRcStickDeflection(int32_t axis, uint16_t midrc);
|
||||
int32_t getRcStickDeflection(int32_t axis);
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef enum {
|
|||
BOXLEDLOW = 12,
|
||||
BOXLIGHTS = 13,
|
||||
BOXNAVLAUNCH = 14,
|
||||
// BOXOSD = 15,
|
||||
BOXOSD = 15,
|
||||
BOXTELEMETRY = 16,
|
||||
BOXBLACKBOX = 17,
|
||||
BOXFAILSAFE = 18,
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
#include "common/string_light.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
#include "fc/settings_generated.h"
|
||||
#include "settings_generated.h"
|
||||
|
||||
#include "fc/settings.h"
|
||||
|
||||
#include "fc/settings_generated.c"
|
||||
#include "settings_generated.c"
|
||||
|
||||
void setting_get_name(const setting_t *val, char *buf)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "config/parameter_group.h"
|
||||
|
||||
#include "fc/settings_generated.h"
|
||||
#include "settings_generated.h"
|
||||
|
||||
typedef struct lookupTableEntry_s {
|
||||
const char * const *values;
|
||||
|
|
|
@ -7,7 +7,7 @@ tables:
|
|||
values: ["NONE", "AUTO", "ADXL345", "MPU6050", "MMA845x", "BMA280", "LSM303DLHC", "MPU6000", "MPU6500", "MPU9250", "BMI160", "FAKE"]
|
||||
enum: accelerationSensor_e
|
||||
- name: rangefinder_hardware
|
||||
values: ["NONE", "HCSR04", "SRF10", "HCSR04I2C", "VL53L0X", "MSP", "UIB"]
|
||||
values: ["NONE", "HCSR04", "SRF10", "INAV_I2C", "VL53L0X", "MSP", "UIB"]
|
||||
enum: rangefinderType_e
|
||||
- name: mag_hardware
|
||||
values: ["NONE", "AUTO", "HMC5883", "AK8975", "GPSMAG", "MAG3110", "AK8963", "IST8310", "QMC5883", "MPU9250", "IST8308", "FAKE"]
|
||||
|
@ -67,7 +67,7 @@ tables:
|
|||
- name: i2c_speed
|
||||
values: ["400KHZ", "800KHZ", "100KHZ", "200KHZ"]
|
||||
- name: debug_modes
|
||||
values: ["NONE", "GYRO", "NOTCH", "NAV_LANDING", "FW_ALTITUDE", "AGL", "FLOW_RAW", "SBUS", "FPORT", "ALWAYS", "STAGE2", "WIND_ESTIMATOR"]
|
||||
values: ["NONE", "GYRO", "NOTCH", "NAV_LANDING", "FW_ALTITUDE", "AGL", "FLOW_RAW", "SBUS", "FPORT", "ALWAYS", "STAGE2", "WIND_ESTIMATOR", "SAG_COMP_VOLTAGE"]
|
||||
- name: async_mode
|
||||
values: ["NONE", "GYRO", "ALL"]
|
||||
- name: aux_operator
|
||||
|
@ -321,10 +321,6 @@ groups:
|
|||
- name: receiver_type
|
||||
field: receiverType
|
||||
table: receiver_type
|
||||
- name: mid_rc
|
||||
field: midrc
|
||||
min: MIDRC_MIN
|
||||
max: MIDRC_MAX
|
||||
- name: min_check
|
||||
field: mincheck
|
||||
min: PWM_RANGE_MIN
|
||||
|
@ -427,6 +423,9 @@ groups:
|
|||
- name: motor_pwm_protocol
|
||||
field: motorPwmProtocol
|
||||
table: motor_pwm_protocol
|
||||
- name: throttle_vbat_compensation
|
||||
field: throttleVBatCompensation
|
||||
type: bool
|
||||
|
||||
- name: PG_FAILSAFE_CONFIG
|
||||
type: failsafeConfig_t
|
||||
|
|
|
@ -275,7 +275,7 @@ void failsafeApplyControlInput(void)
|
|||
break;
|
||||
|
||||
case THROTTLE:
|
||||
rcCommand[idx] = feature(FEATURE_3D) ? rxConfig()->midrc : motorConfig()->minthrottle;
|
||||
rcCommand[idx] = feature(FEATURE_3D) ? PWM_RANGE_MIDDLE : motorConfig()->minthrottle;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -330,9 +330,9 @@ static bool failsafeCheckStickMotion(void)
|
|||
if (failsafeConfig()->failsafe_stick_motion_threshold > 0) {
|
||||
uint32_t totalRcDelta = 0;
|
||||
|
||||
totalRcDelta += ABS(rcData[ROLL] - rxConfig()->midrc);
|
||||
totalRcDelta += ABS(rcData[PITCH] - rxConfig()->midrc);
|
||||
totalRcDelta += ABS(rcData[YAW] - rxConfig()->midrc);
|
||||
totalRcDelta += ABS(rcData[ROLL] - PWM_RANGE_MIDDLE);
|
||||
totalRcDelta += ABS(rcData[PITCH] - PWM_RANGE_MIDDLE);
|
||||
totalRcDelta += ABS(rcData[YAW] - PWM_RANGE_MIDDLE);
|
||||
|
||||
return totalRcDelta >= failsafeConfig()->failsafe_stick_motion_threshold;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
|
||||
#include "rx/rx.h"
|
||||
|
||||
#include "sensors/battery.h"
|
||||
|
||||
|
||||
//#define MIXER_DEBUG
|
||||
|
||||
|
@ -87,7 +89,7 @@ PG_RESET_TEMPLATE(mixerConfig_t, mixerConfig,
|
|||
#define DEFAULT_MIN_THROTTLE 1150
|
||||
#endif
|
||||
|
||||
PG_REGISTER_WITH_RESET_TEMPLATE(motorConfig_t, motorConfig, PG_MOTOR_CONFIG, 1);
|
||||
PG_REGISTER_WITH_RESET_TEMPLATE(motorConfig_t, motorConfig, PG_MOTOR_CONFIG, 2);
|
||||
|
||||
PG_RESET_TEMPLATE(motorConfig_t, motorConfig,
|
||||
.minthrottle = DEFAULT_MIN_THROTTLE,
|
||||
|
@ -96,7 +98,8 @@ PG_RESET_TEMPLATE(motorConfig_t, motorConfig,
|
|||
.maxthrottle = 1850,
|
||||
.mincommand = 1000,
|
||||
.motorAccelTimeMs = 0,
|
||||
.motorDecelTimeMs = 0
|
||||
.motorDecelTimeMs = 0,
|
||||
.throttleVBatCompensation = false
|
||||
);
|
||||
|
||||
static motorMixer_t currentMixer[MAX_SUPPORTED_MOTORS];
|
||||
|
@ -284,17 +287,17 @@ void mixTable(const float dT)
|
|||
|
||||
// Find min and max throttle based on condition.
|
||||
if (feature(FEATURE_3D)) {
|
||||
if (!ARMING_FLAG(ARMED)) throttlePrevious = rxConfig()->midrc; // When disarmed set to mid_rc. It always results in positive direction after arming.
|
||||
if (!ARMING_FLAG(ARMED)) throttlePrevious = PWM_RANGE_MIDDLE; // When disarmed set to mid_rc. It always results in positive direction after arming.
|
||||
|
||||
if ((rcCommand[THROTTLE] <= (rxConfig()->midrc - rcControlsConfig()->deadband3d_throttle))) { // Out of band handling
|
||||
if ((rcCommand[THROTTLE] <= (PWM_RANGE_MIDDLE - rcControlsConfig()->deadband3d_throttle))) { // Out of band handling
|
||||
throttleMax = flight3DConfig()->deadband3d_low;
|
||||
throttleMin = motorConfig()->minthrottle;
|
||||
throttlePrevious = throttleCommand = rcCommand[THROTTLE];
|
||||
} else if (rcCommand[THROTTLE] >= (rxConfig()->midrc + rcControlsConfig()->deadband3d_throttle)) { // Positive handling
|
||||
} else if (rcCommand[THROTTLE] >= (PWM_RANGE_MIDDLE + rcControlsConfig()->deadband3d_throttle)) { // Positive handling
|
||||
throttleMax = motorConfig()->maxthrottle;
|
||||
throttleMin = flight3DConfig()->deadband3d_high;
|
||||
throttlePrevious = throttleCommand = rcCommand[THROTTLE];
|
||||
} else if ((throttlePrevious <= (rxConfig()->midrc - rcControlsConfig()->deadband3d_throttle))) { // Deadband handling from negative to positive
|
||||
} else if ((throttlePrevious <= (PWM_RANGE_MIDDLE - rcControlsConfig()->deadband3d_throttle))) { // Deadband handling from negative to positive
|
||||
throttleCommand = throttleMax = flight3DConfig()->deadband3d_low;
|
||||
throttleMin = motorConfig()->minthrottle;
|
||||
} else { // Deadband handling from positive to negative
|
||||
|
@ -305,6 +308,10 @@ void mixTable(const float dT)
|
|||
throttleCommand = rcCommand[THROTTLE];
|
||||
throttleMin = motorConfig()->minthrottle;
|
||||
throttleMax = motorConfig()->maxthrottle;
|
||||
|
||||
// Throttle compensation based on battery voltage
|
||||
if (motorConfig()->throttleVBatCompensation && STATE(FIXED_WING) && isAmperageConfigured() && feature(FEATURE_VBAT))
|
||||
throttleCommand = MIN(throttleCommand * calculateThrottleCompensationFactor(), throttleMax);
|
||||
}
|
||||
|
||||
throttleRange = throttleMax - throttleMin;
|
||||
|
@ -333,7 +340,7 @@ void mixTable(const float dT)
|
|||
if (failsafeIsActive()) {
|
||||
motor[i] = constrain(motor[i], motorConfig()->mincommand, motorConfig()->maxthrottle);
|
||||
} else if (feature(FEATURE_3D)) {
|
||||
if (throttlePrevious <= (rxConfig()->midrc - rcControlsConfig()->deadband3d_throttle)) {
|
||||
if (throttlePrevious <= (PWM_RANGE_MIDDLE - rcControlsConfig()->deadband3d_throttle)) {
|
||||
motor[i] = constrain(motor[i], motorConfig()->minthrottle, flight3DConfig()->deadband3d_low);
|
||||
} else {
|
||||
motor[i] = constrain(motor[i], flight3DConfig()->deadband3d_high, motorConfig()->maxthrottle);
|
||||
|
@ -349,7 +356,7 @@ void mixTable(const float dT)
|
|||
bool userMotorStop = !navigationIsFlyingAutonomousMode() && !failsafeIsActive() && (rcData[THROTTLE] < rxConfig()->mincheck);
|
||||
if (failsafeMotorStop || navMotorStop || userMotorStop) {
|
||||
if (feature(FEATURE_3D)) {
|
||||
motor[i] = rxConfig()->midrc;
|
||||
motor[i] = PWM_RANGE_MIDDLE;
|
||||
}
|
||||
else {
|
||||
motor[i] = motorConfig()->mincommand;
|
||||
|
|
|
@ -80,6 +80,7 @@ typedef struct motorConfig_s {
|
|||
uint8_t motorPwmProtocol;
|
||||
uint16_t motorAccelTimeMs; // Time limit for motor to accelerate from 0 to 100% throttle [ms]
|
||||
uint16_t motorDecelTimeMs; // Time limit for motor to decelerate from 0 to 100% throttle [ms]
|
||||
bool throttleVBatCompensation;
|
||||
} motorConfig_t;
|
||||
|
||||
PG_DECLARE(motorConfig_t, motorConfig);
|
||||
|
|
|
@ -392,8 +392,8 @@ void updatePIDCoefficients(void)
|
|||
static float calcHorizonRateMagnitude(void)
|
||||
{
|
||||
// Figure out the raw stick positions
|
||||
const int32_t stickPosAil = ABS(getRcStickDeflection(FD_ROLL, rxConfig()->midrc));
|
||||
const int32_t stickPosEle = ABS(getRcStickDeflection(FD_PITCH, rxConfig()->midrc));
|
||||
const int32_t stickPosAil = ABS(getRcStickDeflection(FD_ROLL));
|
||||
const int32_t stickPosEle = ABS(getRcStickDeflection(FD_PITCH));
|
||||
const float mostDeflectedStickPos = constrain(MAX(stickPosAil, stickPosEle), 0, 500) / 500.0f;
|
||||
const float modeTransitionStickPos = constrain(pidBank()->pid[PID_LEVEL].D, 0, 100) / 100.0f;
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ void servoMixer(float dT)
|
|||
input[INPUT_STABILIZED_YAW] = axisPID[YAW];
|
||||
|
||||
// Reverse yaw servo when inverted in 3D mode only for multirotor and tricopter
|
||||
if (feature(FEATURE_3D) && (rcData[THROTTLE] < rxConfig()->midrc) &&
|
||||
if (feature(FEATURE_3D) && (rcData[THROTTLE] < PWM_RANGE_MIDDLE) &&
|
||||
(mixerConfig()->platformType == PLATFORM_MULTIROTOR || mixerConfig()->platformType == PLATFORM_TRICOPTER)) {
|
||||
input[INPUT_STABILIZED_YAW] *= -1;
|
||||
}
|
||||
|
@ -254,22 +254,22 @@ void servoMixer(float dT)
|
|||
// 2000 - 1500 = +500
|
||||
// 1500 - 1500 = 0
|
||||
// 1000 - 1500 = -500
|
||||
input[INPUT_RC_ROLL] = rcData[ROLL] - rxConfig()->midrc;
|
||||
input[INPUT_RC_PITCH] = rcData[PITCH] - rxConfig()->midrc;
|
||||
input[INPUT_RC_YAW] = rcData[YAW] - rxConfig()->midrc;
|
||||
input[INPUT_RC_THROTTLE] = rcData[THROTTLE] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH5] = rcData[AUX1] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH6] = rcData[AUX2] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH7] = rcData[AUX3] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH8] = rcData[AUX4] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH9] = rcData[AUX5] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH10] = rcData[AUX6] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH11] = rcData[AUX7] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH12] = rcData[AUX8] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH13] = rcData[AUX9] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH14] = rcData[AUX10] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH15] = rcData[AUX11] - rxConfig()->midrc;
|
||||
input[INPUT_RC_CH16] = rcData[AUX12] - rxConfig()->midrc;
|
||||
input[INPUT_RC_ROLL] = rcData[ROLL] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_PITCH] = rcData[PITCH] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_YAW] = rcData[YAW] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_THROTTLE] = rcData[THROTTLE] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH5] = rcData[AUX1] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH6] = rcData[AUX2] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH7] = rcData[AUX3] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH8] = rcData[AUX4] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH9] = rcData[AUX5] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH10] = rcData[AUX6] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH11] = rcData[AUX7] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH12] = rcData[AUX8] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH13] = rcData[AUX9] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH14] = rcData[AUX10] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH15] = rcData[AUX11] - PWM_RANGE_MIDDLE;
|
||||
input[INPUT_RC_CH16] = rcData[AUX12] - PWM_RANGE_MIDDLE;
|
||||
|
||||
for (int i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
|
||||
servo[i] = 0;
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
// Adjust OSD_MESSAGE's default position when
|
||||
// changing OSD_MESSAGE_LENGTH
|
||||
#define OSD_MESSAGE_LENGTH 28
|
||||
#define OSD_ALTERNATING_TEXT(ms, num_choices) ((millis() / ms) % num_choices)
|
||||
#define OSD_ALTERNATING_CHOICES(ms, num_choices) ((millis() / ms) % num_choices)
|
||||
#define _CONST_STR_SIZE(s) ((sizeof(s)/sizeof(s[0]))-1) // -1 to avoid counting final '\0'
|
||||
// Wrap all string constants intenteded for display as messages with
|
||||
// this macro to ensure compile time length validation.
|
||||
|
@ -678,13 +678,12 @@ static const char * navigationStateMessage(void)
|
|||
case MW_NAV_STATE_LAND_START:
|
||||
return OSD_MESSAGE_STR("STARTING EMERGENCY LANDING");
|
||||
case MW_NAV_STATE_LAND_IN_PROGRESS:
|
||||
if (!navigationRTHAllowsLanding()) {
|
||||
if (STATE(FIXED_WING)) {
|
||||
return OSD_MESSAGE_STR("LOITERING AROUND HOME");
|
||||
}
|
||||
return OSD_MESSAGE_STR("HOVERING");
|
||||
}
|
||||
return OSD_MESSAGE_STR("LANDING");
|
||||
case MW_NAV_STATE_HOVER_ABOVE_HOME:
|
||||
if (STATE(FIXED_WING)) {
|
||||
return OSD_MESSAGE_STR("LOITERING AROUND HOME");
|
||||
}
|
||||
return OSD_MESSAGE_STR("HOVERING");
|
||||
case MW_NAV_STATE_LANDED:
|
||||
return OSD_MESSAGE_STR("LANDED");
|
||||
case MW_NAV_STATE_LAND_SETTLE:
|
||||
|
@ -934,9 +933,9 @@ static void osdDrawMap(int referenceHeading, uint8_t referenceSym, uint8_t cente
|
|||
break;
|
||||
}
|
||||
|
||||
if (STATE(GPS_FIX) && poiDistance > scale) {
|
||||
if (STATE(GPS_FIX)) {
|
||||
|
||||
int directionToPoi = osdGetHeadingAngle(poiDirection + referenceHeading);
|
||||
int directionToPoi = osdGetHeadingAngle(poiDirection - referenceHeading);
|
||||
float poiAngle = DEGREES_TO_RADIANS(directionToPoi);
|
||||
float poiSin = sin_approx(poiAngle);
|
||||
float poiCos = cos_approx(poiAngle);
|
||||
|
@ -947,7 +946,7 @@ static void osdDrawMap(int referenceHeading, uint8_t referenceSym, uint8_t cente
|
|||
int points = poiDistance / (float)(scale / charHeight);
|
||||
|
||||
float pointsX = points * poiSin;
|
||||
int poiX = midX + roundf(pointsX / charWidth);
|
||||
int poiX = midX - roundf(pointsX / charWidth);
|
||||
if (poiX < minX || poiX > maxX) {
|
||||
continue;
|
||||
}
|
||||
|
@ -958,18 +957,21 @@ static void osdDrawMap(int referenceHeading, uint8_t referenceSym, uint8_t cente
|
|||
continue;
|
||||
}
|
||||
|
||||
if (poiX == midX && poiY == midY && centerSym != SYM_BLANK) {
|
||||
if (poiX == midX && poiY == midY) {
|
||||
// We're over the map center symbol, so we would be drawing
|
||||
// over it even if we increased the scale. No reason to run
|
||||
// this loop 50 times.
|
||||
break;
|
||||
}
|
||||
// over it even if we increased the scale. Alternate between
|
||||
// drawing the center symbol or drawing the POI.
|
||||
if (centerSym != SYM_BLANK && OSD_ALTERNATING_CHOICES(1000, 2) == 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
uint8_t c;
|
||||
if (displayReadCharWithAttr(osdDisplayPort, poiY, poiY, &c, NULL) && c != SYM_BLANK) {
|
||||
// Something else written here, increase scale. If the display doesn't support reading
|
||||
// back characters, we assume there's nothing.
|
||||
continue;
|
||||
uint8_t c;
|
||||
if (displayReadCharWithAttr(osdDisplayPort, poiY, poiY, &c, NULL) && c != SYM_BLANK) {
|
||||
// Something else written here, increase scale. If the display doesn't support reading
|
||||
// back characters, we assume there's nothing.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the point on the map
|
||||
|
@ -1050,6 +1052,19 @@ static bool osdDrawSingleElement(uint8_t item)
|
|||
displayWriteWithAttr(osdDisplayPort, elemPosX + 1, elemPosY, buff, elemAttr);
|
||||
return true;
|
||||
|
||||
case OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE:
|
||||
osdFormatBatteryChargeSymbol(buff);
|
||||
buff[1] = '\0';
|
||||
osdUpdateBatteryCapacityOrVoltageTextAttributes(&elemAttr);
|
||||
displayWriteWithAttr(osdDisplayPort, elemPosX, elemPosY, buff, elemAttr);
|
||||
elemAttr = TEXT_ATTRIBUTES_NONE;
|
||||
osdFormatCentiNumber(buff, getSagCompensatedBatteryVoltage(), 0, osdConfig()->main_voltage_decimals, 0, osdConfig()->main_voltage_decimals + 2);
|
||||
strcat(buff, "V");
|
||||
if ((getBatteryState() != BATTERY_NOT_PRESENT) && (getSagCompensatedBatteryVoltage() <= getBatteryWarningVoltage()))
|
||||
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
|
||||
displayWriteWithAttr(osdDisplayPort, elemPosX + 1, elemPosY, buff, elemAttr);
|
||||
return true;
|
||||
|
||||
case OSD_CURRENT_DRAW:
|
||||
buff[0] = SYM_AMP;
|
||||
osdFormatCentiNumber(buff + 1, getAmperage(), 0, 2, 0, 3);
|
||||
|
@ -1590,7 +1605,7 @@ static bool osdDrawSingleElement(uint8_t item)
|
|||
messages[messageCount++] = navStateFSMessage;
|
||||
}
|
||||
if (messageCount > 0) {
|
||||
message = messages[OSD_ALTERNATING_TEXT(1000, messageCount)];
|
||||
message = messages[OSD_ALTERNATING_CHOICES(1000, messageCount)];
|
||||
if (message == failsafeInfoMessage) {
|
||||
// failsafeInfoMessage is not useful for recovering
|
||||
// a lost model, but might help avoiding a crash.
|
||||
|
@ -1630,12 +1645,12 @@ static bool osdDrawSingleElement(uint8_t item)
|
|||
// Pick one of the available messages. Each message lasts
|
||||
// a second.
|
||||
if (messageCount > 0) {
|
||||
message = messages[OSD_ALTERNATING_TEXT(1000, messageCount)];
|
||||
message = messages[OSD_ALTERNATING_CHOICES(1000, messageCount)];
|
||||
}
|
||||
}
|
||||
} else if (ARMING_FLAG(ARMING_DISABLED_ALL_FLAGS)) {
|
||||
// Check if we're unable to arm for some reason
|
||||
if (OSD_ALTERNATING_TEXT(1000, 2) == 0) {
|
||||
if (OSD_ALTERNATING_CHOICES(1000, 2) == 0) {
|
||||
message = "UNABLE TO ARM";
|
||||
TEXT_ATTRIBUTES_ADD_INVERTED(elemAttr);
|
||||
} else {
|
||||
|
@ -1895,6 +1910,8 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
{
|
||||
osdConfig->item_pos[0][OSD_ALTITUDE] = OSD_POS(1, 0) | OSD_VISIBLE_FLAG;
|
||||
osdConfig->item_pos[0][OSD_MAIN_BATT_VOLTAGE] = OSD_POS(12, 0) | OSD_VISIBLE_FLAG;
|
||||
osdConfig->item_pos[0][OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE] = OSD_POS(12, 1);
|
||||
|
||||
osdConfig->item_pos[0][OSD_RSSI_VALUE] = OSD_POS(23, 0) | OSD_VISIBLE_FLAG;
|
||||
//line 2
|
||||
osdConfig->item_pos[0][OSD_HOME_DIST] = OSD_POS(1, 1);
|
||||
|
@ -2224,6 +2241,12 @@ static void osdRefresh(timeUs_t currentTimeUs)
|
|||
{
|
||||
static timeUs_t lastTimeUs = 0;
|
||||
|
||||
if (IS_RC_MODE_ACTIVE(BOXOSD) && (!cmsInMenu)) {
|
||||
displayClearScreen(osdDisplayPort);
|
||||
armState = ARMING_FLAG(ARMED);
|
||||
return;
|
||||
}
|
||||
|
||||
// detect arm/disarm
|
||||
if (armState != ARMING_FLAG(ARMED)) {
|
||||
if (ARMING_FLAG(ARMED)) {
|
||||
|
|
|
@ -83,6 +83,7 @@ typedef enum {
|
|||
OSD_DEBUG, // Number 46. Intentionally absent from configurator and CMS. Set it from CLI.
|
||||
OSD_WIND_SPEED_HORIZONTAL,
|
||||
OSD_WIND_SPEED_VERTICAL,
|
||||
OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE,
|
||||
OSD_ITEM_COUNT // MUST BE LAST
|
||||
} osd_items_e;
|
||||
|
||||
|
|
|
@ -199,6 +199,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_INITIALIZE(navigati
|
|||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_CLIMB_TO_SAFE_ALT(navigationFSMState_t previousState);
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HEAD_HOME(navigationFSMState_t previousState);
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING(navigationFSMState_t previousState);
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_ABOVE_HOME(navigationFSMState_t previousState);
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LANDING(navigationFSMState_t previousState);
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_FINISHING(navigationFSMState_t previousState);
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_FINISHED(navigationFSMState_t previousState);
|
||||
|
@ -368,6 +369,24 @@ static const navigationFSMStateDescriptor_t navFSM[NAV_STATE_COUNT] = {
|
|||
.onEvent = {
|
||||
[NAV_FSM_EVENT_TIMEOUT] = NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING,
|
||||
[NAV_FSM_EVENT_SUCCESS] = NAV_STATE_RTH_LANDING,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME] = NAV_STATE_RTH_HOVER_ABOVE_HOME,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_IDLE] = NAV_STATE_IDLE,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_ALTHOLD] = NAV_STATE_ALTHOLD_INITIALIZE,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_POSHOLD_3D] = NAV_STATE_POSHOLD_3D_INITIALIZE,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING] = NAV_STATE_EMERGENCY_LANDING_INITIALIZE,
|
||||
}
|
||||
},
|
||||
|
||||
[NAV_STATE_RTH_HOVER_ABOVE_HOME] = {
|
||||
.persistentId = NAV_PERSISTENT_ID_RTH_HOVER_ABOVE_HOME,
|
||||
.onEntry = navOnEnteringState_NAV_STATE_RTH_HOVER_ABOVE_HOME,
|
||||
.timeoutMs = 500,
|
||||
.stateFlags = NAV_CTL_ALT | NAV_CTL_POS | NAV_CTL_YAW | NAV_REQUIRE_ANGLE | NAV_REQUIRE_MAGHOLD | NAV_REQUIRE_THRTILT | NAV_AUTO_RTH | NAV_RC_POS | NAV_RC_YAW | NAV_RC_ALT,
|
||||
.mapToFlightModes = NAV_RTH_MODE | NAV_ALTHOLD_MODE,
|
||||
.mwState = MW_NAV_STATE_HOVER_ABOVE_HOME,
|
||||
.mwError = MW_NAV_ERROR_NONE,
|
||||
.onEvent = {
|
||||
[NAV_FSM_EVENT_TIMEOUT] = NAV_STATE_RTH_HOVER_ABOVE_HOME,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_IDLE] = NAV_STATE_IDLE,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_ALTHOLD] = NAV_STATE_ALTHOLD_INITIALIZE,
|
||||
[NAV_FSM_EVENT_SWITCH_TO_POSHOLD_3D] = NAV_STATE_POSHOLD_3D_INITIALIZE,
|
||||
|
@ -784,7 +803,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_INITIALIZE(navigati
|
|||
|
||||
// If close to home - reset home position and land
|
||||
if (posControl.homeDistance < navConfig()->general.min_rth_distance) {
|
||||
setHomePosition(&navGetCurrentActualPositionAndVelocity()->pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_HEADING);
|
||||
setHomePosition(&navGetCurrentActualPositionAndVelocity()->pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_HEADING, NAV_HOME_VALID_ALL);
|
||||
setDesiredPosition(&navGetCurrentActualPositionAndVelocity()->pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING);
|
||||
|
||||
return NAV_FSM_EVENT_SWITCH_TO_RTH_LANDING; // NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING
|
||||
|
@ -932,12 +951,12 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LAND
|
|||
// Wait until target heading is reached (with 15 deg margin for error)
|
||||
if (STATE(FIXED_WING)) {
|
||||
resetLandingDetector();
|
||||
return NAV_FSM_EVENT_SUCCESS;
|
||||
return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME;
|
||||
}
|
||||
else {
|
||||
if (ABS(wrap_18000(posControl.homeWaypointAbove.yaw - posControl.actualState.yaw)) < DEGREES_TO_CENTIDEGREES(15)) {
|
||||
resetLandingDetector();
|
||||
return NAV_FSM_EVENT_SUCCESS;
|
||||
return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME;
|
||||
}
|
||||
else if (!validateRTHSanityChecker()) {
|
||||
// Continue to check for RTH sanity during pre-landing hover
|
||||
|
@ -954,6 +973,16 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LAND
|
|||
}
|
||||
}
|
||||
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_ABOVE_HOME(navigationFSMState_t previousState)
|
||||
{
|
||||
UNUSED(previousState);
|
||||
|
||||
if (!(validateRTHSanityChecker() || (posControl.flags.estPosStatus >= EST_USABLE) || !checkForPositionSensorTimeout()))
|
||||
return NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING;
|
||||
|
||||
return NAV_FSM_EVENT_NONE;
|
||||
}
|
||||
|
||||
static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LANDING(navigationFSMState_t previousState)
|
||||
{
|
||||
UNUSED(previousState);
|
||||
|
@ -970,28 +999,26 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LANDING(navigationF
|
|||
return NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING;
|
||||
}
|
||||
|
||||
if (navigationRTHAllowsLanding()) {
|
||||
float descentVelLimited = 0;
|
||||
float descentVelLimited = 0;
|
||||
|
||||
// A safeguard - if surface altitude sensors is available and it is reading < 50cm altitude - drop to low descend speed
|
||||
if ((posControl.flags.estAglStatus == EST_TRUSTED) && posControl.actualState.agl.pos.z < 50.0f) {
|
||||
// land_descent_rate == 200 : descend speed = 30 cm/s, gentle touchdown
|
||||
// Do not allow descent velocity slower than -30cm/s so the landing detector works.
|
||||
descentVelLimited = MIN(-0.15f * navConfig()->general.land_descent_rate, -30.0f);
|
||||
}
|
||||
else {
|
||||
// Ramp down descent velocity from 100% at maxAlt altitude to 25% from minAlt to 0cm.
|
||||
float descentVelScaling = (navGetCurrentActualPositionAndVelocity()->pos.z - posControl.homePosition.pos.z - navConfig()->general.land_slowdown_minalt)
|
||||
/ (navConfig()->general.land_slowdown_maxalt - navConfig()->general.land_slowdown_minalt) * 0.75f + 0.25f; // Yield 1.0 at 2000 alt and 0.25 at 500 alt
|
||||
|
||||
descentVelScaling = constrainf(descentVelScaling, 0.25f, 1.0f);
|
||||
|
||||
// Do not allow descent velocity slower than -50cm/s so the landing detector works.
|
||||
descentVelLimited = MIN(-descentVelScaling * navConfig()->general.land_descent_rate, -50.0f);
|
||||
}
|
||||
|
||||
updateClimbRateToAltitudeController(descentVelLimited, ROC_TO_ALT_NORMAL);
|
||||
// A safeguard - if surface altitude sensors is available and it is reading < 50cm altitude - drop to low descend speed
|
||||
if ((posControl.flags.estAglStatus == EST_TRUSTED) && posControl.actualState.agl.pos.z < 50.0f) {
|
||||
// land_descent_rate == 200 : descend speed = 30 cm/s, gentle touchdown
|
||||
// Do not allow descent velocity slower than -30cm/s so the landing detector works.
|
||||
descentVelLimited = MIN(-0.15f * navConfig()->general.land_descent_rate, -30.0f);
|
||||
}
|
||||
else {
|
||||
// Ramp down descent velocity from 100% at maxAlt altitude to 25% from minAlt to 0cm.
|
||||
float descentVelScaling = (navGetCurrentActualPositionAndVelocity()->pos.z - posControl.homePosition.pos.z - navConfig()->general.land_slowdown_minalt)
|
||||
/ (navConfig()->general.land_slowdown_maxalt - navConfig()->general.land_slowdown_minalt) * 0.75f + 0.25f; // Yield 1.0 at 2000 alt and 0.25 at 500 alt
|
||||
|
||||
descentVelScaling = constrainf(descentVelScaling, 0.25f, 1.0f);
|
||||
|
||||
// Do not allow descent velocity slower than -50cm/s so the landing detector works.
|
||||
descentVelLimited = MIN(-descentVelScaling * navConfig()->general.land_descent_rate, -50.0f);
|
||||
}
|
||||
|
||||
updateClimbRateToAltitudeController(descentVelLimited, ROC_TO_ALT_NORMAL);
|
||||
|
||||
return NAV_FSM_EVENT_NONE;
|
||||
}
|
||||
|
@ -1331,12 +1358,16 @@ float navPidApply3(pidController_t *pid, const float setpoint, const float measu
|
|||
newProportional = error * pid->param.kP * gainScaler;
|
||||
|
||||
/* D-term */
|
||||
if (pid->reset) {
|
||||
pid->last_input = (pidFlags & PID_DTERM_FROM_ERROR) ? error : measurement;
|
||||
pid->reset = false;
|
||||
}
|
||||
|
||||
if (pidFlags & PID_DTERM_FROM_ERROR) {
|
||||
/* Error-tracking D-term */
|
||||
newDerivative = (error - pid->last_input) / dt;
|
||||
pid->last_input = error;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* Measurement tracking D-term */
|
||||
newDerivative = -(measurement - pid->last_input) / dt;
|
||||
pid->last_input = measurement;
|
||||
|
@ -1378,6 +1409,7 @@ float navPidApply2(pidController_t *pid, const float setpoint, const float measu
|
|||
|
||||
void navPidReset(pidController_t *pid)
|
||||
{
|
||||
pid->reset = true;
|
||||
pid->integrator = 0.0f;
|
||||
pid->last_input = 0.0f;
|
||||
pid->dterm_filter_state.state = 0.0f;
|
||||
|
@ -1532,9 +1564,30 @@ void updateActualAltitudeAndClimbRate(bool estimateValid, float newAltitude, flo
|
|||
*-----------------------------------------------------------*/
|
||||
void updateActualHeading(bool headingValid, int32_t newHeading)
|
||||
{
|
||||
/* Update heading */
|
||||
/* Update heading. Check if we're acquiring a valid heading for the
|
||||
* first time and update home heading accordingly.
|
||||
*/
|
||||
navigationEstimateStatus_e newEstHeading = headingValid ? EST_TRUSTED : EST_NONE;
|
||||
if (newEstHeading >= EST_USABLE && posControl.flags.estHeadingStatus < EST_USABLE &&
|
||||
(posControl.homeFlags & (NAV_HOME_VALID_XY | NAV_HOME_VALID_Z)) &&
|
||||
(posControl.homeFlags & NAV_HOME_VALID_HEADING) == 0) {
|
||||
|
||||
// Home was stored using the fake heading (assuming boot as 0deg). Calculate
|
||||
// the offset from the fake to the actual yaw and apply the same rotation
|
||||
// to the home point.
|
||||
int32_t fakeToRealYawOffset = newHeading - posControl.actualState.yaw;
|
||||
|
||||
posControl.homePosition.yaw += fakeToRealYawOffset;
|
||||
if (posControl.homePosition.yaw < 0) {
|
||||
posControl.homePosition.yaw += DEGREES_TO_CENTIDEGREES(360);
|
||||
}
|
||||
if (posControl.homePosition.yaw >= DEGREES_TO_CENTIDEGREES(360)) {
|
||||
posControl.homePosition.yaw -= DEGREES_TO_CENTIDEGREES(360);
|
||||
}
|
||||
posControl.homeFlags |= NAV_HOME_VALID_HEADING;
|
||||
}
|
||||
posControl.actualState.yaw = newHeading;
|
||||
posControl.flags.estHeadingStatus = headingValid ? EST_TRUSTED : EST_NONE;
|
||||
posControl.flags.estHeadingStatus = newEstHeading;
|
||||
|
||||
/* Precompute sin/cos of yaw angle */
|
||||
posControl.actualState.sinYaw = sin_approx(CENTIDEGREES_TO_RADIANS(newHeading));
|
||||
|
@ -1678,30 +1731,43 @@ bool validateRTHSanityChecker(void)
|
|||
/*-----------------------------------------------------------
|
||||
* Reset home position to current position
|
||||
*-----------------------------------------------------------*/
|
||||
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask)
|
||||
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask, navigationHomeFlags_t homeFlags)
|
||||
{
|
||||
// XY-position
|
||||
if ((useMask & NAV_POS_UPDATE_XY) != 0) {
|
||||
posControl.homePosition.pos.x = pos->x;
|
||||
posControl.homePosition.pos.y = pos->y;
|
||||
if (homeFlags & NAV_HOME_VALID_XY) {
|
||||
posControl.homeFlags |= NAV_HOME_VALID_XY;
|
||||
} else {
|
||||
posControl.homeFlags &= ~NAV_HOME_VALID_XY;
|
||||
}
|
||||
}
|
||||
|
||||
// Z-position
|
||||
if ((useMask & NAV_POS_UPDATE_Z) != 0) {
|
||||
posControl.homePosition.pos.z = pos->z;
|
||||
if (homeFlags & NAV_HOME_VALID_Z) {
|
||||
posControl.homeFlags |= NAV_HOME_VALID_Z;
|
||||
} else {
|
||||
posControl.homeFlags &= ~NAV_HOME_VALID_Z;
|
||||
}
|
||||
}
|
||||
|
||||
// Heading
|
||||
if ((useMask & NAV_POS_UPDATE_HEADING) != 0) {
|
||||
// Heading
|
||||
posControl.homePosition.yaw = yaw;
|
||||
if (homeFlags & NAV_HOME_VALID_HEADING) {
|
||||
posControl.homeFlags |= NAV_HOME_VALID_HEADING;
|
||||
} else {
|
||||
posControl.homeFlags &= ~NAV_HOME_VALID_HEADING;
|
||||
}
|
||||
}
|
||||
|
||||
posControl.homeDistance = 0;
|
||||
posControl.homeDirection = 0;
|
||||
|
||||
posControl.flags.isHomeValid = true;
|
||||
|
||||
// Update target RTH altitude as a waypoint above home
|
||||
posControl.homeWaypointAbove = posControl.homePosition;
|
||||
updateDesiredRTHAltitude();
|
||||
|
@ -1710,6 +1776,21 @@ void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t
|
|||
ENABLE_STATE(GPS_FIX_HOME);
|
||||
}
|
||||
|
||||
static navigationHomeFlags_t navigationActualStateHomeValidity(void)
|
||||
{
|
||||
navigationHomeFlags_t flags = 0;
|
||||
|
||||
if (posControl.flags.estPosStatus >= EST_USABLE) {
|
||||
flags |= NAV_HOME_VALID_XY | NAV_HOME_VALID_Z;
|
||||
}
|
||||
|
||||
if (posControl.flags.estHeadingStatus >= EST_USABLE) {
|
||||
flags |= NAV_HOME_VALID_HEADING;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Update home position, calculate distance and bearing to home
|
||||
*-----------------------------------------------------------*/
|
||||
|
@ -1718,7 +1799,8 @@ void updateHomePosition(void)
|
|||
// Disarmed and have a valid position, constantly update home
|
||||
if (!ARMING_FLAG(ARMED)) {
|
||||
if (posControl.flags.estPosStatus >= EST_USABLE) {
|
||||
bool setHome = !posControl.flags.isHomeValid;
|
||||
const navigationHomeFlags_t validHomeFlags = NAV_HOME_VALID_XY | NAV_HOME_VALID_Z;
|
||||
bool setHome = (posControl.homeFlags & validHomeFlags) != validHomeFlags;
|
||||
switch ((nav_reset_type_e)positionEstimationConfig()->reset_home_type) {
|
||||
case NAV_RESET_NEVER:
|
||||
break;
|
||||
|
@ -1730,7 +1812,7 @@ void updateHomePosition(void)
|
|||
break;
|
||||
}
|
||||
if (setHome) {
|
||||
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING );
|
||||
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING, navigationActualStateHomeValidity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1741,7 +1823,7 @@ void updateHomePosition(void)
|
|||
if (IS_RC_MODE_ACTIVE(BOXHOMERESET)) {
|
||||
if (isHomeResetAllowed && !FLIGHT_MODE(FAILSAFE_MODE) && !FLIGHT_MODE(NAV_RTH_MODE) && !FLIGHT_MODE(NAV_WP_MODE) && (posControl.flags.estPosStatus >= EST_USABLE)) {
|
||||
const navSetWaypointFlags_t homeUpdateFlags = STATE(GPS_FIX_HOME) ? (NAV_POS_UPDATE_XY | NAV_POS_UPDATE_HEADING) : (NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING);
|
||||
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, homeUpdateFlags);
|
||||
setHomePosition(&posControl.actualState.abs.pos, posControl.actualState.yaw, homeUpdateFlags, navigationActualStateHomeValidity());
|
||||
isHomeResetAllowed = false;
|
||||
}
|
||||
}
|
||||
|
@ -2120,7 +2202,7 @@ void setWaypoint(uint8_t wpNumber, const navWaypoint_t * wpData)
|
|||
if ((wpNumber == 0) && ARMING_FLAG(ARMED) && (posControl.flags.estPosStatus >= EST_USABLE) && posControl.gpsOrigin.valid && posControl.flags.isGCSAssistedNavigationEnabled) {
|
||||
// Forcibly set home position. Note that this is only valid if already armed, otherwise home will be reset instantly
|
||||
geoConvertGeodeticToLocal(&posControl.gpsOrigin, &wpLLH, &wpPos.pos, GEO_ALT_RELATIVE);
|
||||
setHomePosition(&wpPos.pos, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING);
|
||||
setHomePosition(&wpPos.pos, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING, NAV_HOME_VALID_ALL);
|
||||
}
|
||||
// WP #255 - special waypoint - directly set desiredPosition
|
||||
// Only valid when armed and in poshold mode
|
||||
|
@ -2441,9 +2523,13 @@ static navigationFSMEvent_t selectNavEventFromBoxModeInput(void)
|
|||
}
|
||||
}
|
||||
else {
|
||||
// If we were in LAUNCH mode - force switch to IDLE
|
||||
// If we were in LAUNCH mode - force switch to IDLE only if the throttle is low
|
||||
if (FLIGHT_MODE(NAV_LAUNCH_MODE)) {
|
||||
return NAV_FSM_EVENT_SWITCH_TO_IDLE;
|
||||
throttleStatus_e throttleStatus = calculateThrottleStatus();
|
||||
if (throttleStatus != THROTTLE_LOW)
|
||||
return NAV_FSM_EVENT_NONE;
|
||||
else
|
||||
return NAV_FSM_EVENT_SWITCH_TO_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2554,8 +2640,8 @@ bool navigationTerrainFollowingEnabled(void)
|
|||
|
||||
bool navigationBlockArming(void)
|
||||
{
|
||||
const bool navBoxModesEnabled = IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP) || IS_RC_MODE_ACTIVE(BOXNAVPOSHOLD);
|
||||
const bool navLaunchComboModesEnabled = isNavLaunchEnabled() && (IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP));
|
||||
const bool navBoxModesEnabled = IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP) || IS_RC_MODE_ACTIVE(BOXNAVPOSHOLD) || (STATE(FIXED_WING) && IS_RC_MODE_ACTIVE(BOXNAVALTHOLD));
|
||||
const bool navLaunchComboModesEnabled = isNavLaunchEnabled() && (IS_RC_MODE_ACTIVE(BOXNAVRTH) || IS_RC_MODE_ACTIVE(BOXNAVWP) || IS_RC_MODE_ACTIVE(BOXNAVALTHOLD));
|
||||
bool shouldBlockArming = false;
|
||||
|
||||
if (!navConfig()->general.flags.extra_arming_safety)
|
||||
|
@ -2767,7 +2853,7 @@ rthState_e getStateOfForcedRTH(void)
|
|||
bool navigationIsControllingThrottle(void)
|
||||
{
|
||||
navigationFSMStateFlags_t stateFlags = navGetCurrentStateFlags();
|
||||
return (stateFlags & (NAV_CTL_ALT | NAV_CTL_EMERG | NAV_CTL_LAUNCH | NAV_CTL_LAND)) || (STATE(FIXED_WING) && (stateFlags & (NAV_CTL_POS)));
|
||||
return (stateFlags & (NAV_CTL_ALT | NAV_CTL_EMERG | NAV_CTL_LAUNCH | NAV_CTL_LAND));
|
||||
}
|
||||
|
||||
bool navigationIsFlyingAutonomousMode(void)
|
||||
|
|
|
@ -230,7 +230,8 @@ typedef enum {
|
|||
MW_NAV_STATE_LAND_IN_PROGRESS, // Land in Progress
|
||||
MW_NAV_STATE_LANDED, // Landed
|
||||
MW_NAV_STATE_LAND_SETTLE, // Settling before land
|
||||
MW_NAV_STATE_LAND_START_DESCENT // Start descent
|
||||
MW_NAV_STATE_LAND_START_DESCENT, // Start descent
|
||||
MW_NAV_STATE_HOVER_ABOVE_HOME // Hover/Loitering above home
|
||||
} navSystemStatus_State_e;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -412,28 +412,24 @@ int16_t applyFixedWingMinSpeedController(timeUs_t currentTimeUs)
|
|||
|
||||
void applyFixedWingPitchRollThrottleController(navigationFSMStateFlags_t navStateFlags, timeUs_t currentTimeUs)
|
||||
{
|
||||
int16_t pitchCorrection = 0; // >0 climb, <0 dive
|
||||
int16_t rollCorrection = 0; // >0 right, <0 left
|
||||
int16_t throttleCorrection = 0; // raw throttle
|
||||
|
||||
int16_t minThrottleCorrection = navConfig()->fw.min_throttle - navConfig()->fw.cruise_throttle;
|
||||
int16_t maxThrottleCorrection = navConfig()->fw.max_throttle - navConfig()->fw.cruise_throttle;
|
||||
|
||||
// Mix Pitch/Roll/Throttle
|
||||
if (isRollAdjustmentValid && (navStateFlags & NAV_CTL_POS)) {
|
||||
rollCorrection += posControl.rcAdjustment[ROLL];
|
||||
// ROLL >0 right, <0 left
|
||||
int16_t rollCorrection = constrain(posControl.rcAdjustment[ROLL], -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle));
|
||||
rcCommand[ROLL] = pidAngleToRcCommand(rollCorrection, pidProfile()->max_angle_inclination[FD_ROLL]);
|
||||
}
|
||||
|
||||
if (isPitchAdjustmentValid && (navStateFlags & NAV_CTL_ALT)) {
|
||||
pitchCorrection += posControl.rcAdjustment[PITCH];
|
||||
throttleCorrection += DECIDEGREES_TO_DEGREES(pitchCorrection) * navConfig()->fw.pitch_to_throttle;
|
||||
// PITCH >0 dive, <0 climb
|
||||
int16_t pitchCorrection = constrain(posControl.rcAdjustment[PITCH], -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle));
|
||||
rcCommand[PITCH] = -pidAngleToRcCommand(pitchCorrection, pidProfile()->max_angle_inclination[FD_PITCH]);
|
||||
int16_t throttleCorrection = DECIDEGREES_TO_DEGREES(pitchCorrection) * navConfig()->fw.pitch_to_throttle;
|
||||
|
||||
#ifdef NAV_FIXED_WING_LANDING
|
||||
if (navStateFlags & NAV_CTL_LAND) {
|
||||
/*
|
||||
* During LAND we do not allow to raise THROTTLE when nose is up
|
||||
* to reduce speed
|
||||
*/
|
||||
// During LAND we do not allow to raise THROTTLE when nose is up to reduce speed
|
||||
throttleCorrection = constrain(throttleCorrection, minThrottleCorrection, 0);
|
||||
} else {
|
||||
#endif
|
||||
|
@ -441,28 +437,13 @@ void applyFixedWingPitchRollThrottleController(navigationFSMStateFlags_t navStat
|
|||
#ifdef NAV_FIXED_WING_LANDING
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Speed controller - only apply in POS mode when NOT NAV_CTL_LAND
|
||||
if ((navStateFlags & NAV_CTL_POS) && !(navStateFlags & NAV_CTL_LAND)) {
|
||||
throttleCorrection += applyFixedWingMinSpeedController(currentTimeUs);
|
||||
throttleCorrection = constrain(throttleCorrection, minThrottleCorrection, maxThrottleCorrection);
|
||||
}
|
||||
// Speed controller - only apply in POS mode when NOT NAV_CTL_LAND
|
||||
if ((navStateFlags & NAV_CTL_POS) && !(navStateFlags & NAV_CTL_LAND)) {
|
||||
throttleCorrection += applyFixedWingMinSpeedController(currentTimeUs);
|
||||
throttleCorrection = constrain(throttleCorrection, minThrottleCorrection, maxThrottleCorrection);
|
||||
}
|
||||
|
||||
// Limit and apply
|
||||
if (isPitchAdjustmentValid && (navStateFlags & NAV_CTL_ALT)) {
|
||||
// PITCH correction is measured according to altitude: <0 - dive/lose altitude, >0 - climb/gain altitude
|
||||
// PITCH angle is measured in opposite direction ( >0 - dive, <0 - climb)
|
||||
pitchCorrection = constrain(pitchCorrection, -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle));
|
||||
rcCommand[PITCH] = -pidAngleToRcCommand(pitchCorrection, pidProfile()->max_angle_inclination[FD_PITCH]);
|
||||
}
|
||||
|
||||
if (isRollAdjustmentValid && (navStateFlags & NAV_CTL_POS)) {
|
||||
rollCorrection = constrain(rollCorrection, -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_bank_angle));
|
||||
rcCommand[ROLL] = pidAngleToRcCommand(rollCorrection, pidProfile()->max_angle_inclination[FD_ROLL]);
|
||||
}
|
||||
|
||||
if ((navStateFlags & NAV_CTL_ALT) || (navStateFlags & NAV_CTL_POS)) {
|
||||
uint16_t correctedThrottleValue = constrain(navConfig()->fw.cruise_throttle + throttleCorrection, navConfig()->fw.min_throttle, navConfig()->fw.max_throttle);
|
||||
rcCommand[THROTTLE] = constrain(correctedThrottleValue, motorConfig()->minthrottle, motorConfig()->maxthrottle);
|
||||
}
|
||||
|
@ -475,23 +456,15 @@ void applyFixedWingPitchRollThrottleController(navigationFSMStateFlags_t navStat
|
|||
if (navStateFlags & NAV_CTL_LAND) {
|
||||
if ( ((posControl.flags.estAltStatus >= EST_USABLE) && (navGetCurrentActualPositionAndVelocity()->pos.z <= navConfig()->general.land_slowdown_minalt)) ||
|
||||
((posControl.flags.estAglStatus == EST_TRUSTED) && (posControl.actualState.agl.pos.z <= navConfig()->general.land_slowdown_minalt)) ) {
|
||||
/*
|
||||
* Set motor to min. throttle and stop it when MOTOR_STOP feature is enabled
|
||||
*/
|
||||
|
||||
// Set motor to min. throttle and stop it when MOTOR_STOP feature is enabled
|
||||
rcCommand[THROTTLE] = motorConfig()->minthrottle;
|
||||
ENABLE_STATE(NAV_MOTOR_STOP_OR_IDLE);
|
||||
|
||||
/*
|
||||
* Stabilize ROLL axis on 0 degrees banking regardless of loiter radius and position
|
||||
*/
|
||||
// Stabilize ROLL axis on 0 degrees banking regardless of loiter radius and position
|
||||
rcCommand[ROLL] = 0;
|
||||
|
||||
/*
|
||||
* Stabilize PITCH angle into shallow dive as specified by the
|
||||
* nav_fw_land_dive_angle setting (default value is 2 - defined
|
||||
* in navigation.c).
|
||||
* PITCH angle is measured: >0 - dive, <0 - climb)
|
||||
*/
|
||||
// Stabilize PITCH angle into shallow dive as specified by the nav_fw_land_dive_angle setting (default value is 2 - defined in navigation.c).
|
||||
rcCommand[PITCH] = pidAngleToRcCommand(DEGREES_TO_DECIDEGREES(navConfig()->fw.land_dive_angle), pidProfile()->max_angle_inclination[FD_PITCH]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,14 @@ typedef enum {
|
|||
EST_TRUSTED = 2 // Estimate is usable and based on actual sensor data
|
||||
} navigationEstimateStatus_e;
|
||||
|
||||
typedef enum {
|
||||
NAV_HOME_INVALID = 0,
|
||||
NAV_HOME_VALID_XY = 1 << 0,
|
||||
NAV_HOME_VALID_Z = 1 << 1,
|
||||
NAV_HOME_VALID_HEADING = 1 << 2,
|
||||
NAV_HOME_VALID_ALL = NAV_HOME_VALID_XY | NAV_HOME_VALID_Z | NAV_HOME_VALID_HEADING,
|
||||
} navigationHomeFlags_t;
|
||||
|
||||
typedef struct navigationFlags_s {
|
||||
bool horizontalPositionDataNew;
|
||||
bool verticalPositionDataNew;
|
||||
|
@ -85,8 +93,6 @@ typedef struct navigationFlags_s {
|
|||
bool isTerrainFollowEnabled; // Does iNav use rangefinder for terrain following (adjusting baro altitude target according to rangefinders readings)
|
||||
|
||||
bool forcedRTHActivated;
|
||||
|
||||
bool isHomeValid;
|
||||
} navigationFlags_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -107,6 +113,7 @@ typedef enum {
|
|||
} pidControllerFlags_e;
|
||||
|
||||
typedef struct {
|
||||
bool reset;
|
||||
pidControllerParam_t param;
|
||||
pt1Filter_t dterm_filter_state; // last derivative for low-pass filter
|
||||
float integrator; // integrator value
|
||||
|
@ -163,6 +170,7 @@ typedef enum {
|
|||
NAV_FSM_EVENT_SWITCH_TO_ALTHOLD,
|
||||
NAV_FSM_EVENT_SWITCH_TO_POSHOLD_3D,
|
||||
NAV_FSM_EVENT_SWITCH_TO_RTH,
|
||||
NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME,
|
||||
NAV_FSM_EVENT_SWITCH_TO_WAYPOINT,
|
||||
NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING,
|
||||
NAV_FSM_EVENT_SWITCH_TO_LAUNCH,
|
||||
|
@ -179,43 +187,44 @@ typedef enum {
|
|||
// This enum is used to keep values in blackbox logs stable, so we can
|
||||
// freely change navigationFSMState_t.
|
||||
typedef enum {
|
||||
NAV_PERSISTENT_ID_UNDEFINED = 0, // 0
|
||||
NAV_PERSISTENT_ID_UNDEFINED = 0,
|
||||
|
||||
NAV_PERSISTENT_ID_IDLE, // 1
|
||||
NAV_PERSISTENT_ID_IDLE = 1,
|
||||
|
||||
NAV_PERSISTENT_ID_ALTHOLD_INITIALIZE, // 2
|
||||
NAV_PERSISTENT_ID_ALTHOLD_IN_PROGRESS, // 3
|
||||
NAV_PERSISTENT_ID_ALTHOLD_INITIALIZE = 2,
|
||||
NAV_PERSISTENT_ID_ALTHOLD_IN_PROGRESS = 3,
|
||||
|
||||
NAV_PERSISTENT_ID_UNUSED_1, // 4, was NAV_STATE_POSHOLD_2D_INITIALIZE
|
||||
NAV_PERSISTENT_ID_UNUSED_2, // 5, was NAV_STATE_POSHOLD_2D_IN_PROGRESS
|
||||
NAV_PERSISTENT_ID_UNUSED_1 = 4, // was NAV_STATE_POSHOLD_2D_INITIALIZE
|
||||
NAV_PERSISTENT_ID_UNUSED_2 = 5, // was NAV_STATE_POSHOLD_2D_IN_PROGRESS
|
||||
|
||||
NAV_PERSISTENT_ID_POSHOLD_3D_INITIALIZE, // 6
|
||||
NAV_PERSISTENT_ID_POSHOLD_3D_IN_PROGRESS, // 7
|
||||
NAV_PERSISTENT_ID_POSHOLD_3D_INITIALIZE = 6,
|
||||
NAV_PERSISTENT_ID_POSHOLD_3D_IN_PROGRESS = 7,
|
||||
|
||||
NAV_PERSISTENT_ID_RTH_INITIALIZE, // 8
|
||||
NAV_PERSISTENT_ID_RTH_CLIMB_TO_SAFE_ALT, // 9
|
||||
NAV_PERSISTENT_ID_RTH_HEAD_HOME, // 10
|
||||
NAV_PERSISTENT_ID_RTH_HOVER_PRIOR_TO_LANDING, // 11
|
||||
NAV_PERSISTENT_ID_RTH_LANDING, // 12
|
||||
NAV_PERSISTENT_ID_RTH_FINISHING, // 13
|
||||
NAV_PERSISTENT_ID_RTH_FINISHED, // 14
|
||||
NAV_PERSISTENT_ID_RTH_INITIALIZE = 8,
|
||||
NAV_PERSISTENT_ID_RTH_CLIMB_TO_SAFE_ALT = 9,
|
||||
NAV_PERSISTENT_ID_RTH_HEAD_HOME = 10,
|
||||
NAV_PERSISTENT_ID_RTH_HOVER_PRIOR_TO_LANDING = 11,
|
||||
NAV_PERSISTENT_ID_RTH_HOVER_ABOVE_HOME = 29,
|
||||
NAV_PERSISTENT_ID_RTH_LANDING = 12,
|
||||
NAV_PERSISTENT_ID_RTH_FINISHING = 13,
|
||||
NAV_PERSISTENT_ID_RTH_FINISHED = 14,
|
||||
|
||||
NAV_PERSISTENT_ID_WAYPOINT_INITIALIZE, // 15
|
||||
NAV_PERSISTENT_ID_WAYPOINT_PRE_ACTION, // 16
|
||||
NAV_PERSISTENT_ID_WAYPOINT_IN_PROGRESS, // 17
|
||||
NAV_PERSISTENT_ID_WAYPOINT_REACHED, // 18
|
||||
NAV_PERSISTENT_ID_WAYPOINT_NEXT, // 19
|
||||
NAV_PERSISTENT_ID_WAYPOINT_FINISHED, // 20
|
||||
NAV_PERSISTENT_ID_WAYPOINT_RTH_LAND, // 21
|
||||
NAV_PERSISTENT_ID_WAYPOINT_INITIALIZE = 15,
|
||||
NAV_PERSISTENT_ID_WAYPOINT_PRE_ACTION = 16,
|
||||
NAV_PERSISTENT_ID_WAYPOINT_IN_PROGRESS = 17,
|
||||
NAV_PERSISTENT_ID_WAYPOINT_REACHED = 18,
|
||||
NAV_PERSISTENT_ID_WAYPOINT_NEXT = 19,
|
||||
NAV_PERSISTENT_ID_WAYPOINT_FINISHED = 20,
|
||||
NAV_PERSISTENT_ID_WAYPOINT_RTH_LAND = 21,
|
||||
|
||||
NAV_PERSISTENT_ID_EMERGENCY_LANDING_INITIALIZE, // 22
|
||||
NAV_PERSISTENT_ID_EMERGENCY_LANDING_IN_PROGRESS, // 23
|
||||
NAV_PERSISTENT_ID_EMERGENCY_LANDING_FINISHED, // 24
|
||||
NAV_PERSISTENT_ID_EMERGENCY_LANDING_INITIALIZE = 22,
|
||||
NAV_PERSISTENT_ID_EMERGENCY_LANDING_IN_PROGRESS = 23,
|
||||
NAV_PERSISTENT_ID_EMERGENCY_LANDING_FINISHED = 24,
|
||||
|
||||
NAV_PERSISTENT_ID_LAUNCH_INITIALIZE, // 25
|
||||
NAV_PERSISTENT_ID_LAUNCH_WAIT, // 26
|
||||
NAV_PERSISTENT_ID_UNUSED_3, // 27, was NAV_STATE_LAUNCH_MOTOR_DELAY
|
||||
NAV_PERSISTENT_ID_LAUNCH_IN_PROGRESS, // 28
|
||||
NAV_PERSISTENT_ID_LAUNCH_INITIALIZE = 25,
|
||||
NAV_PERSISTENT_ID_LAUNCH_WAIT = 26,
|
||||
NAV_PERSISTENT_ID_UNUSED_3 = 27, // was NAV_STATE_LAUNCH_MOTOR_DELAY
|
||||
NAV_PERSISTENT_ID_LAUNCH_IN_PROGRESS = 28,
|
||||
} navigationPersistentId_e;
|
||||
|
||||
typedef enum {
|
||||
|
@ -233,6 +242,7 @@ typedef enum {
|
|||
NAV_STATE_RTH_CLIMB_TO_SAFE_ALT,
|
||||
NAV_STATE_RTH_HEAD_HOME,
|
||||
NAV_STATE_RTH_HOVER_PRIOR_TO_LANDING,
|
||||
NAV_STATE_RTH_HOVER_ABOVE_HOME,
|
||||
NAV_STATE_RTH_LANDING,
|
||||
NAV_STATE_RTH_FINISHING,
|
||||
NAV_STATE_RTH_FINISHED,
|
||||
|
@ -326,6 +336,7 @@ typedef struct {
|
|||
rthSanityChecker_t rthSanityChecker;
|
||||
navWaypointPosition_t homePosition; // Special waypoint, stores original yaw (heading when launched)
|
||||
navWaypointPosition_t homeWaypointAbove; // NEU-coordinates and initial bearing + desired RTH altitude
|
||||
navigationHomeFlags_t homeFlags;
|
||||
|
||||
uint32_t homeDistance; // cm
|
||||
int32_t homeDirection; // deg*100
|
||||
|
@ -362,7 +373,7 @@ bool isLandingDetected(void);
|
|||
|
||||
navigationFSMStateFlags_t navGetCurrentStateFlags(void);
|
||||
|
||||
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask);
|
||||
void setHomePosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask, navigationHomeFlags_t homeFlags);
|
||||
void setDesiredPosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlags_t useMask);
|
||||
void setDesiredSurfaceOffset(float surfaceOffset);
|
||||
void setDesiredPositionToFarAwayTarget(int32_t yaw, int32_t distance, navSetWaypointFlags_t useMask);
|
||||
|
|
|
@ -257,7 +257,7 @@ void crsfRxSendTelemetryData(void)
|
|||
bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) {
|
||||
crsfChannelData[ii] = (16 * rxConfig->midrc) / 10 - 1408;
|
||||
crsfChannelData[ii] = (16 * PWM_RANGE_MIDDLE) / 10 - 1408;
|
||||
}
|
||||
|
||||
rxRuntimeConfig->channelCount = CRSF_MAX_CHANNEL;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#define FPORT_MIN_TELEMETRY_RESPONSE_DELAY_US 500
|
||||
#define FPORT_MAX_TELEMETRY_AGE_MS 500
|
||||
|
||||
#define FPORT_TELEMETRY_MAX_CONSECUTIVE_SENSORS 2 // Needed to avoid lost sensors on FPort, see #3198
|
||||
|
||||
#define FPORT_FRAME_MARKER 0x7E
|
||||
|
||||
|
@ -340,7 +341,17 @@ static bool fportProcessFrame(const rxRuntimeConfig_t *rxRuntimeConfig)
|
|||
if (clearToSend) {
|
||||
DEBUG_SET(DEBUG_FPORT, DEBUG_FPORT_TELEMETRY_DELAY, currentTimeUs - lastTelemetryFrameReceivedUs);
|
||||
|
||||
processSmartPortTelemetry(mspPayload, &clearToSend, NULL);
|
||||
uint8_t *consecutiveSensorCount = rxRuntimeConfig->frameData;
|
||||
if (*consecutiveSensorCount >= FPORT_TELEMETRY_MAX_CONSECUTIVE_SENSORS && !smartPortPayloadContainsMSP(mspPayload)) {
|
||||
// Stop one cycle to avoid saturating the buffer in the RX, since the
|
||||
// downstream bandwidth doesn't allow sensor sensors on every cycle.
|
||||
// We allow MSP frames to run over the resting period, expecting that
|
||||
// the caller won't flood us with requests.
|
||||
*consecutiveSensorCount = 0;
|
||||
} else {
|
||||
(*consecutiveSensorCount)++;
|
||||
processSmartPortTelemetry(mspPayload, &clearToSend, NULL);
|
||||
}
|
||||
|
||||
if (clearToSend) {
|
||||
smartPortWriteFrameFport(&emptySmartPortFrame);
|
||||
|
@ -358,8 +369,10 @@ static bool fportProcessFrame(const rxRuntimeConfig_t *rxRuntimeConfig)
|
|||
bool fportRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
static uint16_t sbusChannelData[SBUS_MAX_CHANNEL];
|
||||
static uint8_t consecutiveSensorCount = 0;
|
||||
rxRuntimeConfig->channelData = sbusChannelData;
|
||||
sbusChannelsInit(rxConfig, rxRuntimeConfig);
|
||||
rxRuntimeConfig->frameData = &consecutiveSensorCount;
|
||||
sbusChannelsInit(rxRuntimeConfig);
|
||||
|
||||
rxRuntimeConfig->channelCount = SBUS_MAX_CHANNEL;
|
||||
rxRuntimeConfig->rxRefreshRate = 11000;
|
||||
|
|
|
@ -113,7 +113,6 @@ PG_REGISTER_WITH_RESET_TEMPLATE(rxConfig_t, rxConfig, PG_RX_CONFIG, 4);
|
|||
#define DEFAULT_RX_TYPE RX_TYPE_NONE
|
||||
#endif
|
||||
|
||||
#define RX_MIDRC 1500
|
||||
#define RX_MIN_USEX 885
|
||||
PG_RESET_TEMPLATE(rxConfig_t, rxConfig,
|
||||
.receiverType = DEFAULT_RX_TYPE,
|
||||
|
@ -123,7 +122,6 @@ PG_RESET_TEMPLATE(rxConfig_t, rxConfig,
|
|||
.rx_spi_protocol = RX_SPI_DEFAULT_PROTOCOL,
|
||||
.spektrum_sat_bind = 0,
|
||||
.serialrx_inverted = 0,
|
||||
.midrc = RX_MIDRC,
|
||||
.mincheck = 1100,
|
||||
.maxcheck = 1900,
|
||||
.rx_min_usec = RX_MIN_USEX, // any of first 4 channels below this value will trigger rx loss detection
|
||||
|
@ -244,11 +242,11 @@ void rxInit(void)
|
|||
rcSampleIndex = 0;
|
||||
|
||||
for (int i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) {
|
||||
rcData[i] = rxConfig()->midrc;
|
||||
rcData[i] = PWM_RANGE_MIDDLE;
|
||||
rcInvalidPulsPeriod[i] = millis() + MAX_INVALID_PULS_TIME;
|
||||
}
|
||||
|
||||
rcData[THROTTLE] = (feature(FEATURE_3D)) ? rxConfig()->midrc : rxConfig()->rx_min_usec;
|
||||
rcData[THROTTLE] = (feature(FEATURE_3D)) ? PWM_RANGE_MIDDLE : rxConfig()->rx_min_usec;
|
||||
|
||||
// Initialize ARM switch to OFF position when arming via switch is defined
|
||||
for (int i = 0; i < MAX_MODE_ACTIVATION_CONDITION_COUNT; i++) {
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef struct rxConfig_s {
|
|||
uint8_t rssi_channel;
|
||||
uint8_t rssi_scale;
|
||||
uint8_t rssiInvert;
|
||||
uint16_t midrc; // Some radios have not a neutral point centered on 1500. can be changed here
|
||||
uint16_t __reserved; // was micrd
|
||||
uint16_t mincheck; // minimum rc end
|
||||
uint16_t maxcheck; // maximum rc end
|
||||
uint16_t rx_min_usec;
|
||||
|
|
|
@ -193,7 +193,7 @@ bool sbusInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
|||
|
||||
rxRuntimeConfig->channelData = sbusChannelData;
|
||||
rxRuntimeConfig->frameData = &sbusFrameData;
|
||||
sbusChannelsInit(rxConfig, rxRuntimeConfig);
|
||||
sbusChannelsInit(rxRuntimeConfig);
|
||||
|
||||
rxRuntimeConfig->channelCount = SBUS_MAX_CHANNEL;
|
||||
rxRuntimeConfig->rxRefreshRate = 11000;
|
||||
|
|
|
@ -84,11 +84,11 @@ static uint16_t sbusChannelsReadRawRC(const rxRuntimeConfig_t *rxRuntimeConfig,
|
|||
return (5 * rxRuntimeConfig->channelData[chan] / 8) + 880;
|
||||
}
|
||||
|
||||
void sbusChannelsInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
void sbusChannelsInit(rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
rxRuntimeConfig->rcReadRawFn = sbusChannelsReadRawRC;
|
||||
for (int b = 0; b < SBUS_MAX_CHANNEL; b++) {
|
||||
rxRuntimeConfig->channelData[b] = (16 * rxConfig->midrc) / 10 - 1408;
|
||||
rxRuntimeConfig->channelData[b] = (16 * PWM_RANGE_MIDDLE) / 10 - 1408;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -49,4 +49,4 @@ typedef struct sbusChannels_s {
|
|||
|
||||
uint8_t sbusChannelsDecode(rxRuntimeConfig_t *rxRuntimeConfig, const sbusChannels_t *channels);
|
||||
|
||||
void sbusChannelsInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig);
|
||||
void sbusChannelsInit(rxRuntimeConfig_t *rxRuntimeConfig);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "io/beeper.h"
|
||||
|
||||
#include "build/debug.h"
|
||||
|
||||
#define ADCVREF 3300 // in mV (3300 = 3.3V)
|
||||
|
||||
|
@ -65,6 +66,8 @@ static bool batteryFullWhenPluggedIn = false;
|
|||
static uint16_t vbat = 0; // battery voltage in 0.1V steps (filtered)
|
||||
static uint16_t vbatLatestADC = 0; // most recent unsmoothed raw reading from vbat ADC
|
||||
static uint16_t amperageLatestADC = 0; // most recent raw reading from current ADC
|
||||
static uint16_t powerSupplyImpedance = 0; // calculated impedance in milliohm
|
||||
static uint16_t sagCompensatedVBat = 0; // calculated no load vbat
|
||||
|
||||
static int32_t amperage = 0; // amperage read by current sensor in centiampere (1/100th A)
|
||||
static int32_t power = 0; // power draw in cW (0.01W resolution)
|
||||
|
@ -122,20 +125,20 @@ void batteryInit(void)
|
|||
batteryCriticalVoltage = 0;
|
||||
}
|
||||
|
||||
static void updateBatteryVoltage(uint32_t vbatTimeDelta)
|
||||
static void updateBatteryVoltage(timeUs_t timeDelta)
|
||||
{
|
||||
uint16_t vbatSample;
|
||||
static pt1Filter_t vbatFilterState;
|
||||
|
||||
// store the battery voltage with some other recent battery voltage readings
|
||||
vbatSample = vbatLatestADC = adcGetChannel(ADC_BATTERY);
|
||||
vbatSample = pt1FilterApply4(&vbatFilterState, vbatSample, VBATT_LPF_FREQ, vbatTimeDelta * 1e-6f);
|
||||
vbatSample = pt1FilterApply4(&vbatFilterState, vbatSample, VBATT_LPF_FREQ, timeDelta * 1e-6f);
|
||||
vbat = batteryAdcToVoltage(vbatSample);
|
||||
}
|
||||
|
||||
void batteryUpdate(uint32_t vbatTimeDelta)
|
||||
void batteryUpdate(timeUs_t timeDelta)
|
||||
{
|
||||
updateBatteryVoltage(vbatTimeDelta);
|
||||
updateBatteryVoltage(timeDelta);
|
||||
|
||||
/* battery has just been connected*/
|
||||
if (batteryState == BATTERY_NOT_PRESENT && vbat > VBATT_PRESENT_THRESHOLD)
|
||||
|
@ -147,7 +150,7 @@ void batteryUpdate(uint32_t vbatTimeDelta)
|
|||
We only do this on the ground so don't care if we do block, not
|
||||
worse than original code anyway*/
|
||||
delay(VBATT_STABLE_DELAY);
|
||||
updateBatteryVoltage(vbatTimeDelta);
|
||||
updateBatteryVoltage(timeDelta);
|
||||
|
||||
unsigned cells = (batteryAdcToVoltage(vbatLatestADC) / batteryConfig()->voltage.cellDetect) + 1;
|
||||
if (cells > 8) cells = 8; // something is wrong, we expect 8 cells maximum (and autodetection will be problematic at 6+ cells)
|
||||
|
@ -245,6 +248,16 @@ uint16_t getBatteryVoltage(void)
|
|||
return vbat;
|
||||
}
|
||||
|
||||
uint16_t getSagCompensatedBatteryVoltage(void)
|
||||
{
|
||||
return sagCompensatedVBat;
|
||||
}
|
||||
|
||||
float calculateThrottleCompensationFactor(void)
|
||||
{
|
||||
return batteryFullVoltage / sagCompensatedVBat;
|
||||
}
|
||||
|
||||
uint16_t getBatteryVoltageLatestADC(void)
|
||||
{
|
||||
return vbatLatestADC;
|
||||
|
@ -275,7 +288,7 @@ uint32_t getBatteryRemainingCapacity(void)
|
|||
|
||||
bool isAmperageConfigured(void)
|
||||
{
|
||||
return batteryConfig()->current.type != CURRENT_SENSOR_NONE;
|
||||
return feature(FEATURE_CURRENT_METER) && batteryConfig()->current.type != CURRENT_SENSOR_NONE;
|
||||
}
|
||||
|
||||
int32_t getAmperage(void)
|
||||
|
@ -304,7 +317,7 @@ int32_t getMWhDrawn(void)
|
|||
}
|
||||
|
||||
|
||||
void currentMeterUpdate(int32_t timeDelta)
|
||||
void currentMeterUpdate(timeUs_t timeDelta)
|
||||
{
|
||||
static pt1Filter_t amperageFilterState;
|
||||
static int64_t mAhdrawnRaw = 0;
|
||||
|
@ -333,15 +346,51 @@ void currentMeterUpdate(int32_t timeDelta)
|
|||
mAhDrawn = mAhdrawnRaw / (3600 * 100);
|
||||
}
|
||||
|
||||
void powerMeterUpdate(int32_t timeDelta)
|
||||
void powerMeterUpdate(timeUs_t timeDelta)
|
||||
{
|
||||
static int64_t mWhDrawnRaw = 0;
|
||||
uint32_t power_mW = amperage * vbat / 10;
|
||||
power = amperage * vbat / 100; // power unit is cW (0.01W resolution)
|
||||
mWhDrawnRaw += (power_mW * timeDelta) / 10000;
|
||||
int32_t heatLossesCompensatedPower_mW = amperage * vbat / 10 + sq((int64_t)amperage) * powerSupplyImpedance / 10000;
|
||||
mWhDrawnRaw += (int64_t)heatLossesCompensatedPower_mW * timeDelta / 10000;
|
||||
mWhDrawn = mWhDrawnRaw / (3600 * 100);
|
||||
}
|
||||
|
||||
void sagCompensatedVBatUpdate(timeUs_t currentTime)
|
||||
{
|
||||
static timeUs_t recordTimestamp = 0;
|
||||
static int32_t amperageRecord;
|
||||
static uint16_t vbatRecord;
|
||||
|
||||
if (batteryState == BATTERY_NOT_PRESENT) {
|
||||
|
||||
recordTimestamp = 0;
|
||||
powerSupplyImpedance = 0;
|
||||
sagCompensatedVBat = vbat;
|
||||
|
||||
} else {
|
||||
|
||||
if (cmpTimeUs(currentTime, recordTimestamp) > 20000000)
|
||||
recordTimestamp = 0;
|
||||
|
||||
if (!recordTimestamp) {
|
||||
amperageRecord = amperage;
|
||||
vbatRecord = vbat;
|
||||
recordTimestamp = currentTime;
|
||||
} else if ((amperage - amperageRecord >= 400) && ((int16_t)vbatRecord - vbat >= 10)) {
|
||||
powerSupplyImpedance = (int32_t)(vbatRecord - vbat) * 1000 / (amperage - amperageRecord);
|
||||
amperageRecord = amperage;
|
||||
vbatRecord = vbat;
|
||||
recordTimestamp = currentTime;
|
||||
}
|
||||
|
||||
sagCompensatedVBat = MIN(batteryFullVoltage, vbat + powerSupplyImpedance * amperage / 1000);
|
||||
|
||||
}
|
||||
|
||||
DEBUG_SET(DEBUG_SAG_COMP_VOLTAGE, 0, powerSupplyImpedance);
|
||||
DEBUG_SET(DEBUG_SAG_COMP_VOLTAGE, 1, sagCompensatedVBat);
|
||||
}
|
||||
|
||||
uint8_t calculateBatteryPercentage(void)
|
||||
{
|
||||
if (batteryState == BATTERY_NOT_PRESENT)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "config/parameter_group.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
#ifndef VBAT_SCALE_DEFAULT
|
||||
#define VBAT_SCALE_DEFAULT 1100
|
||||
|
@ -83,11 +84,11 @@ uint16_t batteryAdcToVoltage(uint16_t src);
|
|||
batteryState_e getBatteryState(void);
|
||||
bool batteryWasFullWhenPluggedIn(void);
|
||||
bool batteryUsesCapacityThresholds(void);
|
||||
void batteryUpdate(uint32_t vbatTimeDelta);
|
||||
void batteryInit(void);
|
||||
|
||||
bool isBatteryVoltageConfigured(void);
|
||||
uint16_t getBatteryVoltage(void);
|
||||
uint16_t getSagCompensatedBatteryVoltage(void);
|
||||
uint16_t getBatteryVoltageLatestADC(void);
|
||||
uint16_t getBatteryWarningVoltage(void);
|
||||
uint8_t getBatteryCellCount(void);
|
||||
|
@ -101,8 +102,10 @@ int32_t getPower(void);
|
|||
int32_t getMAhDrawn(void);
|
||||
int32_t getMWhDrawn(void);
|
||||
|
||||
void currentMeterUpdate(int32_t lastUpdateAt);
|
||||
|
||||
void powerMeterUpdate(int32_t lastUpdateAt);
|
||||
void batteryUpdate(timeUs_t timeDelta);
|
||||
void currentMeterUpdate(timeUs_t timeDelta);
|
||||
void sagCompensatedVBatUpdate(timeUs_t currentTime);
|
||||
void powerMeterUpdate(timeUs_t timeDelta);
|
||||
|
||||
uint8_t calculateBatteryPercentage(void);
|
||||
float calculateThrottleCompensationFactor(void);
|
||||
|
|
|
@ -169,12 +169,6 @@ static bool rangefinderDetect(rangefinderDev_t * dev, uint8_t rangefinderHardwar
|
|||
return true;
|
||||
}
|
||||
|
||||
void rangefinderResetDynamicThreshold(void)
|
||||
{
|
||||
rangefinder.snrThresholdReached = false;
|
||||
rangefinder.dynamicDistanceThreshold = 0;
|
||||
}
|
||||
|
||||
bool rangefinderInit(void)
|
||||
{
|
||||
if (!rangefinderDetect(&rangefinder.dev, rangefinderConfig()->rangefinder_hardware)) {
|
||||
|
@ -186,9 +180,6 @@ bool rangefinderInit(void)
|
|||
rangefinder.calculatedAltitude = RANGEFINDER_OUT_OF_RANGE;
|
||||
rangefinder.maxTiltCos = cos_approx(DECIDEGREES_TO_RADIANS(rangefinder.dev.detectionConeExtendedDeciDegrees / 2.0f));
|
||||
rangefinder.lastValidResponseTimeMs = millis();
|
||||
rangefinder.snr = 0;
|
||||
|
||||
rangefinderResetDynamicThreshold();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -211,35 +202,6 @@ static int32_t applyMedianFilter(int32_t newReading)
|
|||
return medianFilterReady ? quickMedianFilter5(filterSamples) : newReading;
|
||||
}
|
||||
|
||||
static int16_t computePseudoSnr(int32_t newReading) {
|
||||
#define SNR_SAMPLES 5
|
||||
static int16_t snrSamples[SNR_SAMPLES];
|
||||
static uint8_t snrSampleIndex = 0;
|
||||
static int32_t previousReading = RANGEFINDER_OUT_OF_RANGE;
|
||||
static bool snrReady = false;
|
||||
int16_t pseudoSnr = 0;
|
||||
|
||||
snrSamples[snrSampleIndex] = constrain((int)(pow(newReading - previousReading, 2) / 10), 0, 6400);
|
||||
++snrSampleIndex;
|
||||
if (snrSampleIndex == SNR_SAMPLES) {
|
||||
snrSampleIndex = 0;
|
||||
snrReady = true;
|
||||
}
|
||||
|
||||
previousReading = newReading;
|
||||
|
||||
if (snrReady) {
|
||||
|
||||
for (uint8_t i = 0; i < SNR_SAMPLES; i++) {
|
||||
pseudoSnr += snrSamples[i];
|
||||
}
|
||||
|
||||
return constrain(pseudoSnr, 0, 32000);
|
||||
} else {
|
||||
return RANGEFINDER_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called periodically by the scheduler
|
||||
*/
|
||||
|
@ -252,34 +214,6 @@ timeDelta_t rangefinderUpdate(void)
|
|||
return rangefinder.dev.delayMs * 1000; // to microseconds
|
||||
}
|
||||
|
||||
bool isSurfaceAltitudeValid() {
|
||||
|
||||
/*
|
||||
* Preconditions: raw and calculated altidude > 0
|
||||
* SNR lower than threshold
|
||||
*/
|
||||
if (
|
||||
rangefinder.calculatedAltitude > 0 &&
|
||||
rangefinder.rawAltitude > 0 &&
|
||||
rangefinder.snr < RANGEFINDER_DYNAMIC_THRESHOLD
|
||||
) {
|
||||
|
||||
/*
|
||||
* When critical altitude was determined, distance reported by rangefinder
|
||||
* has to be lower than it to assume healthy readout
|
||||
*/
|
||||
if (rangefinder.snrThresholdReached) {
|
||||
return (rangefinder.rawAltitude < rangefinder.dynamicDistanceThreshold);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last distance measured by the sonar in centimeters. When the ground is too far away, RANGEFINDER_OUT_OF_RANGE is returned.
|
||||
*/
|
||||
|
@ -309,20 +243,6 @@ bool rangefinderProcess(float cosTiltAngle)
|
|||
// Invalid response / hardware failure
|
||||
rangefinder.rawAltitude = RANGEFINDER_HARDWARE_FAILURE;
|
||||
}
|
||||
|
||||
rangefinder.snr = computePseudoSnr(distance);
|
||||
|
||||
if (rangefinder.snrThresholdReached == false && rangefinder.rawAltitude > 0) {
|
||||
|
||||
if (rangefinder.snr < RANGEFINDER_DYNAMIC_THRESHOLD && rangefinder.dynamicDistanceThreshold < rangefinder.rawAltitude) {
|
||||
rangefinder.dynamicDistanceThreshold = rangefinder.rawAltitude * RANGEFINDER_DYNAMIC_FACTOR / 100;
|
||||
}
|
||||
|
||||
if (rangefinder.snr >= RANGEFINDER_DYNAMIC_THRESHOLD) {
|
||||
rangefinder.snrThresholdReached = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Bad configuration
|
||||
|
|
|
@ -44,17 +44,12 @@ typedef struct rangefinder_s {
|
|||
int32_t rawAltitude;
|
||||
int32_t calculatedAltitude;
|
||||
timeMs_t lastValidResponseTimeMs;
|
||||
|
||||
bool snrThresholdReached;
|
||||
int32_t dynamicDistanceThreshold;
|
||||
int16_t snr;
|
||||
} rangefinder_t;
|
||||
|
||||
extern rangefinder_t rangefinder;
|
||||
|
||||
const rangefinderHardwarePins_t * rangefinderGetHardwarePins(void);
|
||||
|
||||
void rangefinderResetDynamicThreshold(void);
|
||||
bool rangefinderInit(void);
|
||||
|
||||
int32_t rangefinderGetLatestAltitude(void);
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
#include "telemetry/msp_shared.h"
|
||||
|
||||
#define SMARTPORT_MIN_TELEMETRY_RESPONSE_DELAY_US 500
|
||||
#define SMARTPORT_REST_PERIOD 3 // Needed to avoid lost sensors on FPort, see #3198
|
||||
|
||||
// these data identifiers are obtained from https://github.com/opentx/opentx/blob/master/radio/src/telemetry/frsky_hub.h
|
||||
enum
|
||||
|
@ -138,7 +137,6 @@ enum
|
|||
|
||||
static uint8_t telemetryState = TELEMETRY_STATE_UNINITIALIZED;
|
||||
static uint8_t smartPortIdCnt = 0;
|
||||
static bool smartPortHasRested = false;
|
||||
|
||||
typedef struct smartPortFrame_s {
|
||||
uint8_t sensorId;
|
||||
|
@ -233,6 +231,11 @@ void smartPortSendByte(uint8_t c, uint16_t *checksum, serialPort_t *port)
|
|||
}
|
||||
}
|
||||
|
||||
bool smartPortPayloadContainsMSP(const smartPortPayload_t *payload)
|
||||
{
|
||||
return payload && (payload->frameId == FSSP_MSPC_FRAME_SMARTPORT || payload->frameId == FSSP_MSPC_FRAME_FPORT);
|
||||
}
|
||||
|
||||
void smartPortWriteFrameSerial(const smartPortPayload_t *payload, serialPort_t *port, uint16_t checksum)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)payload;
|
||||
|
@ -343,7 +346,7 @@ void processSmartPortTelemetry(smartPortPayload_t *payload, volatile bool *clear
|
|||
// unless we start receiving other sensors' packets
|
||||
|
||||
#if defined(USE_MSP_OVER_TELEMETRY)
|
||||
if (payload->frameId == FSSP_MSPC_FRAME_SMARTPORT || payload->frameId == FSSP_MSPC_FRAME_FPORT) {
|
||||
if (smartPortPayloadContainsMSP(payload)) {
|
||||
// Pass only the payload: skip frameId
|
||||
uint8_t *frameStart = (uint8_t *)&payload->valueId;
|
||||
smartPortMspReplyPending = handleMspFrame(frameStart, SMARTPORT_MSP_PAYLOAD_SIZE);
|
||||
|
@ -380,14 +383,6 @@ void processSmartPortTelemetry(smartPortPayload_t *payload, volatile bool *clear
|
|||
id = frSkyDataIdTable[smartPortIdCnt];
|
||||
}
|
||||
smartPortIdCnt++;
|
||||
if (smartPortIdCnt % SMARTPORT_REST_PERIOD == 0) {
|
||||
if (!smartPortHasRested) {
|
||||
smartPortIdCnt--;
|
||||
smartPortHasRested = true;
|
||||
return;
|
||||
}
|
||||
smartPortHasRested = false;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case FSSP_DATAID_VFAS :
|
||||
|
|
|
@ -55,3 +55,4 @@ smartPortPayload_t *smartPortDataReceive(uint16_t c, bool *clearToSend, smartPor
|
|||
struct serialPort_s;
|
||||
void smartPortWriteFrameSerial(const smartPortPayload_t *payload, struct serialPort_s *port, uint16_t checksum);
|
||||
void smartPortSendByte(uint8_t c, uint16_t *checksum, struct serialPort_s *port);
|
||||
bool smartPortPayloadContainsMSP(const smartPortPayload_t *payload);
|
||||
|
|
|
@ -65,7 +65,9 @@ class Stamper
|
|||
output = File.join(@stamp_dir, "stamp")
|
||||
stdout, stderr = @compiler.run(input, output, ["-dM", "-E"])
|
||||
File.delete(input)
|
||||
File.delete(output)
|
||||
if File.file?(output)
|
||||
File.delete(output)
|
||||
end
|
||||
return Digest::SHA1.hexdigest(stdout)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,7 +80,10 @@ class Compiler
|
|||
if args
|
||||
all_args.push(*args)
|
||||
end
|
||||
all_args << "-o" << output << input
|
||||
if output
|
||||
all_args << "-o" << output
|
||||
end
|
||||
all_args << input
|
||||
stdout, stderr, compile_status = Open3.capture3(join_args(all_args))
|
||||
raise "Compiler error:\n#{all_args.join(' ')}\n#{stderr}" if not options[:noerror] and not compile_status.success?
|
||||
return stdout, stderr
|
||||
|
|
|
@ -260,10 +260,10 @@ end
|
|||
OFF_ON_TABLE = Hash["name" => "off_on", "values" => ["OFF", "ON"]]
|
||||
|
||||
class Generator
|
||||
def initialize(src_root, settings_file)
|
||||
def initialize(src_root, settings_file, output_dir)
|
||||
@src_root = src_root
|
||||
@settings_file = settings_file
|
||||
@output_dir = File.dirname(settings_file)
|
||||
@output_dir = output_dir || File.dirname(settings_file)
|
||||
|
||||
@compiler = Compiler.new
|
||||
|
||||
|
@ -416,7 +416,7 @@ class Generator
|
|||
}
|
||||
add_header.call("platform.h")
|
||||
add_header.call("config/parameter_group_ids.h")
|
||||
add_header.call("settings.h")
|
||||
add_header.call("fc/settings.h")
|
||||
|
||||
foreach_enabled_group do |group|
|
||||
(group["headers"] || []).each do |h|
|
||||
|
@ -623,10 +623,12 @@ class Generator
|
|||
# Use a temporary dir reachable by relative path
|
||||
# since g++ in cygwin fails to open files
|
||||
# with absolute paths
|
||||
tmp = File.join("obj", "tmp")
|
||||
tmp = File.join(@output_dir, "tmp")
|
||||
FileUtils.mkdir_p(tmp) unless File.directory?(tmp)
|
||||
value = yield(tmp)
|
||||
FileUtils.remove_dir(tmp)
|
||||
if File.directory?(tmp)
|
||||
FileUtils.remove_dir(tmp)
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
|
@ -882,17 +884,20 @@ if __FILE__ == $0
|
|||
exit(1)
|
||||
end
|
||||
|
||||
gen = Generator.new(src_root, settings_file)
|
||||
|
||||
opts = GetoptLong.new(
|
||||
[ "--output-dir", "-o", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--json", "-j", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
)
|
||||
|
||||
jsonFile = nil
|
||||
output_dir = nil
|
||||
|
||||
opts.each do |opt, arg|
|
||||
case opt
|
||||
when "--output-dir"
|
||||
output_dir = arg
|
||||
when "--help"
|
||||
usage()
|
||||
exit(0)
|
||||
|
@ -901,6 +906,8 @@ if __FILE__ == $0
|
|||
end
|
||||
end
|
||||
|
||||
gen = Generator.new(src_root, settings_file, output_dir)
|
||||
|
||||
if jsonFile
|
||||
gen.write_json(jsonFile)
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue