2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
24 #include "blackbox/blackbox.h"
25 #include "blackbox/blackbox_fielddefs.h"
27 #include "common/axis.h"
28 #include "common/maths.h"
29 #include "common/utils.h"
31 #include "config/feature.h"
32 #include "config/parameter_group.h"
33 #include "config/parameter_group_ids.h"
35 #include "drivers/time.h"
36 #include "drivers/vtx_common.h"
38 #include "fc/config.h"
39 #include "fc/controlrate_profile.h"
40 #include "fc/rc_adjustments.h"
41 #include "fc/rc_curves.h"
43 #include "navigation/navigation.h"
45 #include "flight/mixer.h"
46 #include "flight/pid.h"
48 #include "io/beeper.h"
51 #include "sensors/boardalignment.h"
55 PG_REGISTER_ARRAY(adjustmentRange_t
, MAX_ADJUSTMENT_RANGE_COUNT
, adjustmentRanges
, PG_ADJUSTMENT_RANGE_CONFIG
, 0);
57 static uint8_t adjustmentStateMask
= 0;
59 #define MARK_ADJUSTMENT_FUNCTION_AS_BUSY(adjustmentIndex) adjustmentStateMask |= (1 << adjustmentIndex)
60 #define MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex) adjustmentStateMask &= ~(1 << adjustmentIndex)
62 #define IS_ADJUSTMENT_FUNCTION_BUSY(adjustmentIndex) (adjustmentStateMask & (1 << adjustmentIndex))
64 #define RC_ADJUSTMENT_EXPO_MIN 0
65 #define RC_ADJUSTMENT_EXPO_MAX 100
67 #define RC_ADJUSTMENT_MANUAL_RATE_MIN 0
68 #define RC_ADJUSTMENT_MANUAL_RATE_MAX 100
70 #define RC_ADJUSTMENT_PID_MIN 0
71 #define RC_ADJUSTMENT_PID_MAX 200
73 // sync with adjustmentFunction_e
74 static const adjustmentConfig_t defaultAdjustmentConfigs
[ADJUSTMENT_FUNCTION_COUNT
- 1] = {
76 .adjustmentFunction
= ADJUSTMENT_RC_RATE
,
77 .mode
= ADJUSTMENT_MODE_STEP
,
78 .data
= { .stepConfig
= { .step
= 1 }}
80 .adjustmentFunction
= ADJUSTMENT_RC_EXPO
,
81 .mode
= ADJUSTMENT_MODE_STEP
,
82 .data
= { .stepConfig
= { .step
= 1 }}
84 .adjustmentFunction
= ADJUSTMENT_THROTTLE_EXPO
,
85 .mode
= ADJUSTMENT_MODE_STEP
,
86 .data
= { .stepConfig
= { .step
= 1 }}
88 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_RATE
,
89 .mode
= ADJUSTMENT_MODE_STEP
,
90 .data
= { .stepConfig
= { .step
= 1 }}
92 .adjustmentFunction
= ADJUSTMENT_YAW_RATE
,
93 .mode
= ADJUSTMENT_MODE_STEP
,
94 .data
= { .stepConfig
= { .step
= 1 }}
96 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_P
,
97 .mode
= ADJUSTMENT_MODE_STEP
,
98 .data
= { .stepConfig
= { .step
= 1 }}
100 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_I
,
101 .mode
= ADJUSTMENT_MODE_STEP
,
102 .data
= { .stepConfig
= { .step
= 1 }}
104 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_D
,
105 .mode
= ADJUSTMENT_MODE_STEP
,
106 .data
= { .stepConfig
= { .step
= 1 }}
108 .adjustmentFunction
= ADJUSTMENT_YAW_P
,
109 .mode
= ADJUSTMENT_MODE_STEP
,
110 .data
= { .stepConfig
= { .step
= 1 }}
112 .adjustmentFunction
= ADJUSTMENT_YAW_I
,
113 .mode
= ADJUSTMENT_MODE_STEP
,
114 .data
= { .stepConfig
= { .step
= 1 }}
116 .adjustmentFunction
= ADJUSTMENT_YAW_D
,
117 .mode
= ADJUSTMENT_MODE_STEP
,
118 .data
= { .stepConfig
= { .step
= 1 }}
120 .adjustmentFunction
= ADJUSTMENT_RATE_PROFILE
,
121 .mode
= ADJUSTMENT_MODE_STEP
,
122 .data
= { .stepConfig
= { .step
= 1 }}
124 .adjustmentFunction
= ADJUSTMENT_PITCH_RATE
,
125 .mode
= ADJUSTMENT_MODE_STEP
,
126 .data
= { .stepConfig
= { .step
= 1 }}
128 .adjustmentFunction
= ADJUSTMENT_ROLL_RATE
,
129 .mode
= ADJUSTMENT_MODE_STEP
,
130 .data
= { .stepConfig
= { .step
= 1 }}
132 .adjustmentFunction
= ADJUSTMENT_PITCH_P
,
133 .mode
= ADJUSTMENT_MODE_STEP
,
134 .data
= { .stepConfig
= { .step
= 1 }}
136 .adjustmentFunction
= ADJUSTMENT_PITCH_I
,
137 .mode
= ADJUSTMENT_MODE_STEP
,
138 .data
= { .stepConfig
= { .step
= 1 }}
140 .adjustmentFunction
= ADJUSTMENT_PITCH_D
,
141 .mode
= ADJUSTMENT_MODE_STEP
,
142 .data
= { .stepConfig
= { .step
= 1 }}
144 .adjustmentFunction
= ADJUSTMENT_ROLL_P
,
145 .mode
= ADJUSTMENT_MODE_STEP
,
146 .data
= { .stepConfig
= { .step
= 1 }}
148 .adjustmentFunction
= ADJUSTMENT_ROLL_I
,
149 .mode
= ADJUSTMENT_MODE_STEP
,
150 .data
= { .stepConfig
= { .step
= 1 }}
152 .adjustmentFunction
= ADJUSTMENT_ROLL_D
,
153 .mode
= ADJUSTMENT_MODE_STEP
,
154 .data
= { .stepConfig
= { .step
= 1 }}
156 .adjustmentFunction
= ADJUSTMENT_RC_YAW_EXPO
,
157 .mode
= ADJUSTMENT_MODE_STEP
,
158 .data
= { .stepConfig
= { .step
= 1 }}
160 .adjustmentFunction
= ADJUSTMENT_MANUAL_RC_EXPO
,
161 .mode
= ADJUSTMENT_MODE_STEP
,
162 .data
= { .stepConfig
= { .step
= 1 }}
164 .adjustmentFunction
= ADJUSTMENT_MANUAL_RC_YAW_EXPO
,
165 .mode
= ADJUSTMENT_MODE_STEP
,
166 .data
= { .stepConfig
= { .step
= 1 }}
168 .adjustmentFunction
= ADJUSTMENT_MANUAL_PITCH_ROLL_RATE
,
169 .mode
= ADJUSTMENT_MODE_STEP
,
170 .data
= { .stepConfig
= { .step
= 1 }}
172 .adjustmentFunction
= ADJUSTMENT_MANUAL_ROLL_RATE
,
173 .mode
= ADJUSTMENT_MODE_STEP
,
174 .data
= { .stepConfig
= { .step
= 1 }}
176 .adjustmentFunction
= ADJUSTMENT_MANUAL_PITCH_RATE
,
177 .mode
= ADJUSTMENT_MODE_STEP
,
178 .data
= { .stepConfig
= { .step
= 1 }}
180 .adjustmentFunction
= ADJUSTMENT_MANUAL_YAW_RATE
,
181 .mode
= ADJUSTMENT_MODE_STEP
,
182 .data
= { .stepConfig
= { .step
= 1 }}
184 .adjustmentFunction
= ADJUSTMENT_NAV_FW_CRUISE_THR
,
185 .mode
= ADJUSTMENT_MODE_STEP
,
186 .data
= { .stepConfig
= { .step
= 10 }}
188 .adjustmentFunction
= ADJUSTMENT_NAV_FW_PITCH2THR
,
189 .mode
= ADJUSTMENT_MODE_STEP
,
190 .data
= { .stepConfig
= { .step
= 1 }}
192 .adjustmentFunction
= ADJUSTMENT_ROLL_BOARD_ALIGNMENT
,
193 .mode
= ADJUSTMENT_MODE_STEP
,
194 .data
= { .stepConfig
= { .step
= 5 }}
196 .adjustmentFunction
= ADJUSTMENT_PITCH_BOARD_ALIGNMENT
,
197 .mode
= ADJUSTMENT_MODE_STEP
,
198 .data
= { .stepConfig
= { .step
= 5 }}
200 .adjustmentFunction
= ADJUSTMENT_LEVEL_P
,
201 .mode
= ADJUSTMENT_MODE_STEP
,
202 .data
= { .stepConfig
= { .step
= 1 }}
204 .adjustmentFunction
= ADJUSTMENT_LEVEL_I
,
205 .mode
= ADJUSTMENT_MODE_STEP
,
206 .data
= { .stepConfig
= { .step
= 1 }}
208 .adjustmentFunction
= ADJUSTMENT_LEVEL_D
,
209 .mode
= ADJUSTMENT_MODE_STEP
,
210 .data
= { .stepConfig
= { .step
= 1 }}
212 .adjustmentFunction
= ADJUSTMENT_POS_XY_P
,
213 .mode
= ADJUSTMENT_MODE_STEP
,
214 .data
= { .stepConfig
= { .step
= 1 }}
216 .adjustmentFunction
= ADJUSTMENT_POS_XY_I
,
217 .mode
= ADJUSTMENT_MODE_STEP
,
218 .data
= { .stepConfig
= { .step
= 1 }}
220 .adjustmentFunction
= ADJUSTMENT_POS_XY_D
,
221 .mode
= ADJUSTMENT_MODE_STEP
,
222 .data
= { .stepConfig
= { .step
= 1 }}
224 .adjustmentFunction
= ADJUSTMENT_POS_Z_P
,
225 .mode
= ADJUSTMENT_MODE_STEP
,
226 .data
= { .stepConfig
= { .step
= 1 }}
228 .adjustmentFunction
= ADJUSTMENT_POS_Z_I
,
229 .mode
= ADJUSTMENT_MODE_STEP
,
230 .data
= { .stepConfig
= { .step
= 1 }}
232 .adjustmentFunction
= ADJUSTMENT_POS_Z_D
,
233 .mode
= ADJUSTMENT_MODE_STEP
,
234 .data
= { .stepConfig
= { .step
= 1 }}
236 .adjustmentFunction
= ADJUSTMENT_HEADING_P
,
237 .mode
= ADJUSTMENT_MODE_STEP
,
238 .data
= { .stepConfig
= { .step
= 1 }}
240 .adjustmentFunction
= ADJUSTMENT_VEL_XY_P
,
241 .mode
= ADJUSTMENT_MODE_STEP
,
242 .data
= { .stepConfig
= { .step
= 1 }}
244 .adjustmentFunction
= ADJUSTMENT_VEL_XY_I
,
245 .mode
= ADJUSTMENT_MODE_STEP
,
246 .data
= { .stepConfig
= { .step
= 1 }}
248 .adjustmentFunction
= ADJUSTMENT_VEL_XY_D
,
249 .mode
= ADJUSTMENT_MODE_STEP
,
250 .data
= { .stepConfig
= { .step
= 1 }}
252 .adjustmentFunction
= ADJUSTMENT_VEL_Z_P
,
253 .mode
= ADJUSTMENT_MODE_STEP
,
254 .data
= { .stepConfig
= { .step
= 1 }}
256 .adjustmentFunction
= ADJUSTMENT_VEL_Z_I
,
257 .mode
= ADJUSTMENT_MODE_STEP
,
258 .data
= { .stepConfig
= { .step
= 1 }}
260 .adjustmentFunction
= ADJUSTMENT_VEL_Z_D
,
261 .mode
= ADJUSTMENT_MODE_STEP
,
262 .data
= { .stepConfig
= { .step
= 1 }}
264 .adjustmentFunction
= ADJUSTMENT_FW_MIN_THROTTLE_DOWN_PITCH_ANGLE
,
265 .mode
= ADJUSTMENT_MODE_STEP
,
266 .data
= { .stepConfig
= { .step
= 5 }}
268 .adjustmentFunction
= ADJUSTMENT_VTX_POWER_LEVEL
,
269 .mode
= ADJUSTMENT_MODE_STEP
,
270 .data
= { .stepConfig
= { .step
= 1 }}
271 #ifdef USE_INFLIGHT_PROFILE_ADJUSTMENT
273 .adjustmentFunction
= ADJUSTMENT_PROFILE
,
274 .mode
= ADJUSTMENT_MODE_SELECT
,
275 .data
= { .selectConfig
= { .switchPositions
= 3 }}
280 #define ADJUSTMENT_FUNCTION_CONFIG_INDEX_OFFSET 1
282 static adjustmentState_t adjustmentStates
[MAX_SIMULTANEOUS_ADJUSTMENT_COUNT
];
284 static void configureAdjustment(uint8_t index
, uint8_t auxSwitchChannelIndex
, const adjustmentConfig_t
*adjustmentConfig
)
286 adjustmentState_t
* const adjustmentState
= &adjustmentStates
[index
];
288 if (adjustmentState
->config
== adjustmentConfig
) {
289 // already configured
292 adjustmentState
->auxChannelIndex
= auxSwitchChannelIndex
;
293 adjustmentState
->config
= adjustmentConfig
;
294 adjustmentState
->timeoutAt
= 0;
296 MARK_ADJUSTMENT_FUNCTION_AS_READY(index
);
299 static void blackboxLogInflightAdjustmentEvent(adjustmentFunction_e adjustmentFunction
, int32_t newValue
)
302 UNUSED(adjustmentFunction
);
305 if (feature(FEATURE_BLACKBOX
)) {
306 flightLogEvent_inflightAdjustment_t eventData
;
307 eventData
.adjustmentFunction
= adjustmentFunction
;
308 eventData
.newValue
= newValue
;
309 eventData
.floatFlag
= false;
310 blackboxLogEvent(FLIGHT_LOG_EVENT_INFLIGHT_ADJUSTMENT
, (flightLogEventData_t
*)&eventData
);
316 static void blackboxLogInflightAdjustmentEventFloat(adjustmentFunction_e adjustmentFunction
, float newFloatValue
)
319 UNUSED(adjustmentFunction
);
320 UNUSED(newFloatValue
);
322 if (feature(FEATURE_BLACKBOX
)) {
323 flightLogEvent_inflightAdjustment_t eventData
;
324 eventData
.adjustmentFunction
= adjustmentFunction
;
325 eventData
.newFloatValue
= newFloatValue
;
326 eventData
.floatFlag
= true;
327 blackboxLogEvent(FLIGHT_LOG_EVENT_INFLIGHT_ADJUSTMENT
, (flightLogEventData_t
*)&eventData
);
333 static void applyAdjustmentU8(adjustmentFunction_e adjustmentFunction
, uint8_t *val
, int delta
, int low
, int high
)
335 int newValue
= constrain((int)(*val
) + delta
, low
, high
);
337 blackboxLogInflightAdjustmentEvent(adjustmentFunction
, newValue
);
340 static void applyAdjustmentU16(adjustmentFunction_e adjustmentFunction
, uint16_t *val
, int delta
, int low
, int high
)
342 int newValue
= constrain((int)(*val
) + delta
, low
, high
);
344 blackboxLogInflightAdjustmentEvent(adjustmentFunction
, newValue
);
347 static void applyAdjustmentExpo(adjustmentFunction_e adjustmentFunction
, uint8_t *val
, int delta
)
349 applyAdjustmentU8(adjustmentFunction
, val
, delta
, RC_ADJUSTMENT_EXPO_MIN
, RC_ADJUSTMENT_EXPO_MAX
);
352 static void applyAdjustmentManualRate(adjustmentFunction_e adjustmentFunction
, uint8_t *val
, int delta
)
354 return applyAdjustmentU8(adjustmentFunction
, val
, delta
, RC_ADJUSTMENT_MANUAL_RATE_MIN
, RC_ADJUSTMENT_MANUAL_RATE_MAX
);
357 static void applyAdjustmentPID(adjustmentFunction_e adjustmentFunction
, uint8_t *val
, int delta
)
359 applyAdjustmentU8(adjustmentFunction
, val
, delta
, RC_ADJUSTMENT_PID_MIN
, RC_ADJUSTMENT_PID_MAX
);
362 static void applyStepAdjustment(controlRateConfig_t
*controlRateConfig
, uint8_t adjustmentFunction
, int delta
)
365 beeperConfirmationBeeps(2);
367 beeperConfirmationBeeps(1);
369 switch (adjustmentFunction
) {
370 case ADJUSTMENT_RC_EXPO
:
371 applyAdjustmentExpo(ADJUSTMENT_RC_EXPO
, &controlRateConfig
->stabilized
.rcExpo8
, delta
);
373 case ADJUSTMENT_RC_YAW_EXPO
:
374 applyAdjustmentExpo(ADJUSTMENT_RC_YAW_EXPO
, &controlRateConfig
->stabilized
.rcYawExpo8
, delta
);
376 case ADJUSTMENT_MANUAL_RC_EXPO
:
377 applyAdjustmentExpo(ADJUSTMENT_MANUAL_RC_EXPO
, &controlRateConfig
->manual
.rcExpo8
, delta
);
379 case ADJUSTMENT_MANUAL_RC_YAW_EXPO
:
380 applyAdjustmentExpo(ADJUSTMENT_MANUAL_RC_YAW_EXPO
, &controlRateConfig
->manual
.rcYawExpo8
, delta
);
382 case ADJUSTMENT_THROTTLE_EXPO
:
383 applyAdjustmentExpo(ADJUSTMENT_THROTTLE_EXPO
, &controlRateConfig
->throttle
.rcExpo8
, delta
);
385 case ADJUSTMENT_PITCH_ROLL_RATE
:
386 case ADJUSTMENT_PITCH_RATE
:
387 applyAdjustmentU8(ADJUSTMENT_PITCH_RATE
, &controlRateConfig
->stabilized
.rates
[FD_PITCH
], delta
, CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MIN
, CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MAX
);
388 if (adjustmentFunction
== ADJUSTMENT_PITCH_RATE
) {
389 schedulePidGainsUpdate();
392 // follow though for combined ADJUSTMENT_PITCH_ROLL_RATE
395 case ADJUSTMENT_ROLL_RATE
:
396 applyAdjustmentU8(ADJUSTMENT_ROLL_RATE
, &controlRateConfig
->stabilized
.rates
[FD_ROLL
], delta
, CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MIN
, CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MAX
);
397 schedulePidGainsUpdate();
399 case ADJUSTMENT_MANUAL_PITCH_ROLL_RATE
:
400 case ADJUSTMENT_MANUAL_ROLL_RATE
:
401 applyAdjustmentManualRate(ADJUSTMENT_MANUAL_ROLL_RATE
, &controlRateConfig
->manual
.rates
[FD_ROLL
], delta
);
402 if (adjustmentFunction
== ADJUSTMENT_MANUAL_ROLL_RATE
)
404 // follow though for combined ADJUSTMENT_MANUAL_PITCH_ROLL_RATE
406 case ADJUSTMENT_MANUAL_PITCH_RATE
:
407 applyAdjustmentManualRate(ADJUSTMENT_MANUAL_PITCH_RATE
, &controlRateConfig
->manual
.rates
[FD_PITCH
], delta
);
409 case ADJUSTMENT_YAW_RATE
:
410 applyAdjustmentU8(ADJUSTMENT_YAW_RATE
, &controlRateConfig
->stabilized
.rates
[FD_YAW
], delta
, CONTROL_RATE_CONFIG_YAW_RATE_MIN
, CONTROL_RATE_CONFIG_YAW_RATE_MAX
);
411 schedulePidGainsUpdate();
413 case ADJUSTMENT_MANUAL_YAW_RATE
:
414 applyAdjustmentManualRate(ADJUSTMENT_MANUAL_YAW_RATE
, &controlRateConfig
->manual
.rates
[FD_YAW
], delta
);
416 case ADJUSTMENT_PITCH_ROLL_P
:
417 case ADJUSTMENT_PITCH_P
:
418 applyAdjustmentPID(ADJUSTMENT_PITCH_P
, &pidBankMutable()->pid
[PID_PITCH
].P
, delta
);
419 if (adjustmentFunction
== ADJUSTMENT_PITCH_P
) {
420 schedulePidGainsUpdate();
423 // follow though for combined ADJUSTMENT_PITCH_ROLL_P
426 case ADJUSTMENT_ROLL_P
:
427 applyAdjustmentPID(ADJUSTMENT_ROLL_P
, &pidBankMutable()->pid
[PID_ROLL
].P
, delta
);
428 schedulePidGainsUpdate();
430 case ADJUSTMENT_PITCH_ROLL_I
:
431 case ADJUSTMENT_PITCH_I
:
432 applyAdjustmentPID(ADJUSTMENT_PITCH_I
, &pidBankMutable()->pid
[PID_PITCH
].I
, delta
);
433 if (adjustmentFunction
== ADJUSTMENT_PITCH_I
) {
434 schedulePidGainsUpdate();
437 // follow though for combined ADJUSTMENT_PITCH_ROLL_I
440 case ADJUSTMENT_ROLL_I
:
441 applyAdjustmentPID(ADJUSTMENT_ROLL_I
, &pidBankMutable()->pid
[PID_ROLL
].I
, delta
);
442 schedulePidGainsUpdate();
444 case ADJUSTMENT_PITCH_ROLL_D
:
445 case ADJUSTMENT_PITCH_D
:
446 applyAdjustmentPID(ADJUSTMENT_PITCH_D
, &pidBankMutable()->pid
[PID_PITCH
].D
, delta
);
447 if (adjustmentFunction
== ADJUSTMENT_PITCH_D
) {
448 schedulePidGainsUpdate();
451 // follow though for combined ADJUSTMENT_PITCH_ROLL_D
454 case ADJUSTMENT_ROLL_D
:
455 applyAdjustmentPID(ADJUSTMENT_ROLL_D
, &pidBankMutable()->pid
[PID_ROLL
].D
, delta
);
456 schedulePidGainsUpdate();
458 case ADJUSTMENT_YAW_P
:
459 applyAdjustmentPID(ADJUSTMENT_YAW_P
, &pidBankMutable()->pid
[PID_YAW
].P
, delta
);
460 schedulePidGainsUpdate();
462 case ADJUSTMENT_YAW_I
:
463 applyAdjustmentPID(ADJUSTMENT_YAW_I
, &pidBankMutable()->pid
[PID_YAW
].I
, delta
);
464 schedulePidGainsUpdate();
466 case ADJUSTMENT_YAW_D
:
467 applyAdjustmentPID(ADJUSTMENT_YAW_D
, &pidBankMutable()->pid
[PID_YAW
].D
, delta
);
468 schedulePidGainsUpdate();
470 case ADJUSTMENT_NAV_FW_CRUISE_THR
:
471 applyAdjustmentU16(ADJUSTMENT_NAV_FW_CRUISE_THR
, &navConfigMutable()->fw
.cruise_throttle
, delta
, 1000, 2000);
473 case ADJUSTMENT_NAV_FW_PITCH2THR
:
474 applyAdjustmentU8(ADJUSTMENT_NAV_FW_PITCH2THR
, &navConfigMutable()->fw
.pitch_to_throttle
, delta
, 0, 100);
476 case ADJUSTMENT_ROLL_BOARD_ALIGNMENT
:
477 updateBoardAlignment(delta
, 0);
478 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_BOARD_ALIGNMENT
, boardAlignment()->rollDeciDegrees
);
480 case ADJUSTMENT_PITCH_BOARD_ALIGNMENT
:
481 updateBoardAlignment(0, delta
);
482 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_BOARD_ALIGNMENT
, boardAlignment()->pitchDeciDegrees
);
484 case ADJUSTMENT_LEVEL_P
:
485 applyAdjustmentPID(ADJUSTMENT_LEVEL_P
, &pidBankMutable()->pid
[PID_LEVEL
].P
, delta
);
486 // TODO: Need to call something to take it into account?
488 case ADJUSTMENT_LEVEL_I
:
489 applyAdjustmentPID(ADJUSTMENT_LEVEL_I
, &pidBankMutable()->pid
[PID_LEVEL
].I
, delta
);
490 // TODO: Need to call something to take it into account?
492 case ADJUSTMENT_LEVEL_D
:
493 applyAdjustmentPID(ADJUSTMENT_LEVEL_D
, &pidBankMutable()->pid
[PID_LEVEL
].D
, delta
);
494 // TODO: Need to call something to take it into account?
496 case ADJUSTMENT_POS_XY_P
:
497 applyAdjustmentPID(ADJUSTMENT_POS_XY_P
, &pidBankMutable()->pid
[PID_POS_XY
].P
, delta
);
500 case ADJUSTMENT_POS_XY_I
:
501 applyAdjustmentPID(ADJUSTMENT_POS_XY_I
, &pidBankMutable()->pid
[PID_POS_XY
].I
, delta
);
504 case ADJUSTMENT_POS_XY_D
:
505 applyAdjustmentPID(ADJUSTMENT_POS_XY_D
, &pidBankMutable()->pid
[PID_POS_XY
].D
, delta
);
508 case ADJUSTMENT_POS_Z_P
:
509 applyAdjustmentPID(ADJUSTMENT_POS_Z_P
, &pidBankMutable()->pid
[PID_POS_Z
].P
, delta
);
512 case ADJUSTMENT_POS_Z_I
:
513 applyAdjustmentPID(ADJUSTMENT_POS_Z_I
, &pidBankMutable()->pid
[PID_POS_Z
].I
, delta
);
516 case ADJUSTMENT_POS_Z_D
:
517 applyAdjustmentPID(ADJUSTMENT_POS_Z_D
, &pidBankMutable()->pid
[PID_POS_Z
].D
, delta
);
520 case ADJUSTMENT_HEADING_P
:
521 applyAdjustmentPID(ADJUSTMENT_HEADING_P
, &pidBankMutable()->pid
[PID_HEADING
].P
, delta
);
522 // TODO: navigationUsePIDs()?
524 case ADJUSTMENT_VEL_XY_P
:
525 applyAdjustmentPID(ADJUSTMENT_VEL_XY_P
, &pidBankMutable()->pid
[PID_VEL_XY
].P
, delta
);
528 case ADJUSTMENT_VEL_XY_I
:
529 applyAdjustmentPID(ADJUSTMENT_VEL_XY_I
, &pidBankMutable()->pid
[PID_VEL_XY
].I
, delta
);
532 case ADJUSTMENT_VEL_XY_D
:
533 applyAdjustmentPID(ADJUSTMENT_VEL_XY_D
, &pidBankMutable()->pid
[PID_VEL_XY
].D
, delta
);
536 case ADJUSTMENT_VEL_Z_P
:
537 applyAdjustmentPID(ADJUSTMENT_VEL_Z_P
, &pidBankMutable()->pid
[PID_VEL_Z
].P
, delta
);
540 case ADJUSTMENT_VEL_Z_I
:
541 applyAdjustmentPID(ADJUSTMENT_VEL_Z_I
, &pidBankMutable()->pid
[PID_VEL_Z
].I
, delta
);
544 case ADJUSTMENT_VEL_Z_D
:
545 applyAdjustmentPID(ADJUSTMENT_VEL_Z_D
, &pidBankMutable()->pid
[PID_VEL_Z
].D
, delta
);
548 case ADJUSTMENT_FW_MIN_THROTTLE_DOWN_PITCH_ANGLE
:
549 applyAdjustmentU16(ADJUSTMENT_FW_MIN_THROTTLE_DOWN_PITCH_ANGLE
, &mixerConfigMutable()->fwMinThrottleDownPitchAngle
, delta
, 0, FW_MIN_THROTTLE_DOWN_PITCH_ANGLE_MAX
);
551 case ADJUSTMENT_VTX_POWER_LEVEL
:
553 vtxDeviceCapability_t vtxDeviceCapability
;
554 if (vtxCommonGetDeviceCapability(vtxCommonDevice(), &vtxDeviceCapability
)) {
555 applyAdjustmentU8(ADJUSTMENT_VTX_POWER_LEVEL
, &vtxSettingsConfigMutable()->power
, delta
, VTX_SETTINGS_MIN_POWER
, vtxDeviceCapability
.powerCount
);
564 #ifdef USE_INFLIGHT_PROFILE_ADJUSTMENT
565 static void applySelectAdjustment(uint8_t adjustmentFunction
, uint8_t position
)
567 bool applied
= false;
569 switch (adjustmentFunction
) {
570 case ADJUSTMENT_RATE_PROFILE
:
571 if (getCurrentControlRateProfile() != position
) {
572 changeControlRateProfile(position
);
573 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_RATE_PROFILE
, position
);
580 beeperConfirmationBeeps(position
+ 1);
585 #define RESET_FREQUENCY_2HZ (1000 / 2)
587 void processRcAdjustments(controlRateConfig_t
*controlRateConfig
, bool canUseRxData
)
589 const uint32_t now
= millis();
591 for (int adjustmentIndex
= 0; adjustmentIndex
< MAX_SIMULTANEOUS_ADJUSTMENT_COUNT
; adjustmentIndex
++) {
592 adjustmentState_t
* const adjustmentState
= &adjustmentStates
[adjustmentIndex
];
594 if (!adjustmentState
->config
) {
597 const uint8_t adjustmentFunction
= adjustmentState
->config
->adjustmentFunction
;
598 if (adjustmentFunction
== ADJUSTMENT_NONE
) {
602 const int32_t signedDiff
= now
- adjustmentState
->timeoutAt
;
603 const bool canResetReadyStates
= signedDiff
>= 0L;
605 if (canResetReadyStates
) {
606 adjustmentState
->timeoutAt
= now
+ RESET_FREQUENCY_2HZ
;
607 MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex
);
614 const uint8_t channelIndex
= NON_AUX_CHANNEL_COUNT
+ adjustmentState
->auxChannelIndex
;
616 if (adjustmentState
->config
->mode
== ADJUSTMENT_MODE_STEP
) {
618 if (rxGetChannelValue(channelIndex
) > PWM_RANGE_MIDDLE
+ 200) {
619 delta
= adjustmentState
->config
->data
.stepConfig
.step
;
620 } else if (rxGetChannelValue(channelIndex
) < PWM_RANGE_MIDDLE
- 200) {
621 delta
= 0 - adjustmentState
->config
->data
.stepConfig
.step
;
623 // returning the switch to the middle immediately resets the ready state
624 MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex
);
625 adjustmentState
->timeoutAt
= now
+ RESET_FREQUENCY_2HZ
;
628 if (IS_ADJUSTMENT_FUNCTION_BUSY(adjustmentIndex
)) {
632 // it is legitimate to adjust an otherwise const item here
633 applyStepAdjustment(controlRateConfig
, adjustmentFunction
, delta
);
634 #ifdef USE_INFLIGHT_PROFILE_ADJUSTMENT
635 } else if (adjustmentState
->config
->mode
== ADJUSTMENT_MODE_SELECT
) {
636 const uint16_t rangeWidth
= ((2100 - 900) / adjustmentState
->config
->data
.selectConfig
.switchPositions
);
637 const uint8_t position
= (constrain(rxGetChannelValue(channelIndex
), 900, 2100 - 1) - 900) / rangeWidth
;
639 applySelectAdjustment(adjustmentFunction
, position
);
642 MARK_ADJUSTMENT_FUNCTION_AS_BUSY(adjustmentIndex
);
646 void resetAdjustmentStates(void)
648 memset(adjustmentStates
, 0, sizeof(adjustmentStates
));
651 void updateAdjustmentStates(bool canUseRxData
)
653 for (int index
= 0; index
< MAX_ADJUSTMENT_RANGE_COUNT
; index
++) {
654 const adjustmentRange_t
* const adjustmentRange
= adjustmentRanges(index
);
655 if (adjustmentRange
->adjustmentFunction
== ADJUSTMENT_NONE
) {
659 const adjustmentConfig_t
*adjustmentConfig
= &defaultAdjustmentConfigs
[adjustmentRange
->adjustmentFunction
- ADJUSTMENT_FUNCTION_CONFIG_INDEX_OFFSET
];
660 adjustmentState_t
* const adjustmentState
= &adjustmentStates
[adjustmentRange
->adjustmentIndex
];
662 if (canUseRxData
&& isRangeActive(adjustmentRange
->auxChannelIndex
, &adjustmentRange
->range
)) {
663 if (!adjustmentState
->config
) {
664 configureAdjustment(adjustmentRange
->adjustmentIndex
, adjustmentRange
->auxSwitchChannelIndex
, adjustmentConfig
);
667 if (adjustmentState
->config
== adjustmentConfig
) {
668 adjustmentState
->config
= NULL
;
674 bool isAdjustmentFunctionSelected(uint8_t adjustmentFunction
) {
675 for (uint8_t index
= 0; index
< MAX_SIMULTANEOUS_ADJUSTMENT_COUNT
; ++index
) {
676 if (adjustmentStates
[index
].config
&& adjustmentStates
[index
].config
->adjustmentFunction
== adjustmentFunction
) {